You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EditableTableLeak.java 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package com.vaadin.tests.components.table;
  2. import java.io.IOException;
  3. import java.io.ObjectOutputStream;
  4. import java.io.OutputStream;
  5. import java.io.Serializable;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. import com.vaadin.shared.ui.ContentMode;
  9. import com.vaadin.tests.components.TestBase;
  10. import com.vaadin.tests.util.TestUtils;
  11. import com.vaadin.ui.Button;
  12. import com.vaadin.ui.CheckBox;
  13. import com.vaadin.ui.Component;
  14. import com.vaadin.ui.Label;
  15. import com.vaadin.v7.data.Container;
  16. import com.vaadin.v7.ui.DefaultFieldFactory;
  17. import com.vaadin.v7.ui.Field;
  18. import com.vaadin.v7.ui.Table;
  19. public class EditableTableLeak extends TestBase {
  20. private final Table table = new Table("ISO-3166 Country Codes and flags");
  21. private final CheckBox useFieldFactory = new CheckBox(
  22. "Use a caching TableFieldFactory");
  23. private final Label sizeLabel = new Label("", ContentMode.HTML);
  24. private long size = 0;
  25. static class DebugUtils {
  26. private static class ByteCountNullOutputStream extends OutputStream
  27. implements Serializable {
  28. private static final long serialVersionUID = 4220043426041762877L;
  29. private long bytes;
  30. @Override
  31. public void write(int b) {
  32. bytes++;
  33. }
  34. public long getBytes() {
  35. return bytes;
  36. }
  37. }
  38. public static long getSize(Object object) {
  39. try (ByteCountNullOutputStream os = new ByteCountNullOutputStream()) {
  40. ObjectOutputStream oos = new ObjectOutputStream(os);
  41. oos.writeObject(object);
  42. return os.getBytes();
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. return 0;
  46. }
  47. }
  48. }
  49. private static class CachingFieldFactory extends DefaultFieldFactory {
  50. private final Map<Object, Map<Object, Field<?>>> cache = new HashMap<>();
  51. @Override
  52. public Field<?> createField(Container container, Object itemId,
  53. Object propertyId, Component uiContext) {
  54. if (cache.containsKey(itemId)) {
  55. if (cache.get(itemId) != null
  56. && cache.get(itemId).containsKey(propertyId)) {
  57. return cache.get(itemId).get(propertyId);
  58. }
  59. }
  60. Field<?> f = super.createField(container, itemId, propertyId,
  61. uiContext);
  62. if (!cache.containsKey(itemId)) {
  63. cache.put(itemId, new HashMap<Object, Field<?>>());
  64. }
  65. cache.get(itemId).put(propertyId, f);
  66. return f;
  67. }
  68. }
  69. @Override
  70. protected void setup() {
  71. addComponent(useFieldFactory);
  72. useFieldFactory.addValueChangeListener(event -> {
  73. if (useFieldFactory.getValue()) {
  74. table.setTableFieldFactory(new CachingFieldFactory());
  75. } else {
  76. table.setTableFieldFactory(DefaultFieldFactory.get());
  77. }
  78. });
  79. addComponent(table);
  80. table.setEditable(true);
  81. table.setWidth("100%");
  82. table.setHeight("170px");
  83. table.setSelectable(true);
  84. table.setContainerDataSource(TestUtils.getISO3166Container());
  85. table.setColumnHeaders("Country", "Code");
  86. table.setColumnAlignment(TestUtils.iso3166_PROPERTY_SHORT,
  87. Table.ALIGN_CENTER);
  88. table.setColumnExpandRatio(TestUtils.iso3166_PROPERTY_NAME, 1);
  89. table.setColumnWidth(TestUtils.iso3166_PROPERTY_SHORT, 70);
  90. addComponent(sizeLabel);
  91. addComponent(new Button("Show size of the table", event -> {
  92. table.markAsDirtyRecursive();
  93. updateSize();
  94. }));
  95. addComponent(new Button("Select the second row", event -> {
  96. table.select("AL");
  97. updateSize();
  98. }));
  99. }
  100. private void updateSize() {
  101. System.gc();
  102. long newSize = DebugUtils.getSize(table);
  103. sizeLabel.setValue("Size of the table: " + newSize
  104. + " bytes<br/>Delta: " + (newSize - size));
  105. size = newSize;
  106. }
  107. @Override
  108. protected String getDescription() {
  109. return "Table leaks memory while scrolling/selecting when in editable mode";
  110. }
  111. @Override
  112. protected Integer getTicketNumber() {
  113. return 6071;
  114. }
  115. }