Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonah Graham2021-01-20 18:43:39 +0000
committerLars Vogel2021-05-21 08:30:03 +0000
commit1cbd445a39b29c0d88d21cbb0b9d92c8493bf8c5 (patch)
tree63873ad2e8d4fe7a4344f889a107c840356a860e
parent4a15e6430d4bcdf737f3560b64168c82d0ce15e8 (diff)
downloadeclipse.platform.swt-1cbd445a39b29c0d88d21cbb0b9d92c8493bf8c5.tar.gz
eclipse.platform.swt-1cbd445a39b29c0d88d21cbb0b9d92c8493bf8c5.tar.xz
eclipse.platform.swt-1cbd445a39b29c0d88d21cbb0b9d92c8493bf8c5.zip
Bug 561328: Modernize code in Sleak tool
Same functionality, but using Java collections and nicer SWT layouts. This work was done by Conrad, and simply split into new commits by me. Signed-off-by: Jonah Graham <jonah@kichwacoders.com> Also-by: Conrad Groth <info@conrad-groth.de> Change-Id: I5d4548c0b5df48327601ce6462eb5db92b9050f4 Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/175118 Tested-by: Lars Vogel <Lars.Vogel@vogella.com> Reviewed-by: Lars Vogel <Lars.Vogel@vogella.com>
-rw-r--r--bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java266
1 files changed, 125 insertions, 141 deletions
diff --git a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java
index 27246a26c5..641e3f7d78 100644
--- a/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java
+++ b/bundles/org.eclipse.swt.tools.spies/src/org/eclipse/swt/tools/internal/Sleak.java
@@ -14,17 +14,21 @@
package org.eclipse.swt.tools.internal;
import java.io.*;
+import java.util.*;
+import java.util.stream.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.List;
/**
* Instructions on how to use the Sleak tool with a standlaone SWT example:
- *
+ *
* Modify the main method below to launch your application.
* Run Sleak.
- *
+ *
*/
public class Sleak {
List list;
@@ -32,7 +36,7 @@ public class Sleak {
Button enableTracking, snapshot, diff, stackTrace, saveAs, save;
Text text;
Label label;
-
+
String filterPath = "";
String fileName = "sleakout";
String selectedName = null;
@@ -40,10 +44,8 @@ public class Sleak {
boolean saveImages = true;
int fileCount = 0;
- Object [] oldObjects = new Object [0];
- Error [] oldErrors = new Error [0];
- Object [] objects = new Object [0];
- Error [] errors = new Error [0];
+ java.util.List<ObjectWithError> oldObjects = new ArrayList<> ();
+ java.util.List<ObjectWithError> objects = new ArrayList<> ();
public static void main (String [] args) {
DeviceData data = new DeviceData();
@@ -54,21 +56,32 @@ public static void main (String [] args) {
shell.setText ("S-Leak");
Point size = shell.getSize ();
shell.setSize (size.x / 2, size.y / 2);
+ GridLayout layout = new GridLayout(2, false);
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
+ shell.setLayout(layout);
sleak.create (shell);
shell.open();
-
+
// Launch your application here
- // e.g.
-// Shell shell = new Shell(display);
-// Button button1 = new Button(shell, SWT.PUSH);
+ // e.g.
+// Shell shell2 = new Shell(display);
+// Button button1 = new Button(shell2, SWT.PUSH);
// button1.setBounds(10, 10, 100, 50);
// button1.setText("Hello World");
// Image image = new Image(display, 20, 20);
-// Button button2 = new Button(shell, SWT.PUSH);
+// Button button2 = new Button(shell2, SWT.PUSH);
// button2.setBounds(10, 70, 100, 50);
// button2.setImage(image);
-// shell.open();
-
+// button1.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
+// Font oldFont = button1.getFont();
+// int style = oldFont.getFontData()[0].getStyle() ^ SWT.BOLD;
+// button1.setFont(new Font(display, "Arial", 10, style));
+// button1.setForeground(new Color(100,200,100));
+// oldFont.dispose();
+// }));
+// shell2.open();
+
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
@@ -76,39 +89,44 @@ public static void main (String [] args) {
}
public void create (Composite parent) {
- list = new List (parent, SWT.BORDER | SWT.V_SCROLL);
- list.addListener (SWT.Selection, event -> refreshObject ());
- text = new Text (parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
- canvas = new Canvas (parent, SWT.BORDER);
- canvas.addListener (SWT.Paint, event -> paintCanvas (event));
enableTracking = new Button (parent, SWT.CHECK);
enableTracking.setText ("Enable");
enableTracking.setToolTipText("Enable Device resource tracking. Only resources allocated once enabled will be tracked. To track devices created before view is created, turn on tracing options, see https://www.eclipse.org/swt/tools.php");
enableTracking.addListener (SWT.Selection, e -> toggleEnableTracking ());
enableTracking.setSelection(enableTracking.getDisplay().isTracking());
- stackTrace = new Button (parent, SWT.CHECK);
- stackTrace.setText ("Stack");
- stackTrace.addListener (SWT.Selection, e -> toggleStackTrace ());
+ canvas = new Canvas (parent, SWT.BORDER);
+ canvas.addListener (SWT.Paint, event -> paintCanvas (event));
+ canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 10));
+ text = new Text (parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+ text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 10));
+ setVisible(text, false);
snapshot = new Button (parent, SWT.PUSH);
snapshot.setText ("Snap");
snapshot.addListener (SWT.Selection, event -> refreshAll ());
+ snapshot.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false));
diff = new Button (parent, SWT.PUSH);
diff.setText ("Diff");
diff.addListener (SWT.Selection, event -> refreshDifference ());
- label = new Label (parent, SWT.BORDER);
+ diff.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false));
+ stackTrace = new Button (parent, SWT.CHECK);
+ stackTrace.setText ("Stack");
+ stackTrace.addListener (SWT.Selection, e -> toggleStackTrace ());
+ list = new List (parent, SWT.BORDER | SWT.V_SCROLL);
+ list.addListener (SWT.Selection, event -> refreshObject ());
+ list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
+ label = new Label (parent, SWT.NONE);
label.setText ("0 object(s)");
saveAs = new Button (parent, SWT.PUSH);
saveAs.setText ("Save As...");
saveAs.setToolTipText("Saves the contents of the list to a file, optionally with the stack traces if selected.");
saveAs.addListener (SWT.Selection, event -> saveToFile (true));
+ saveAs.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false));
save = new Button (parent, SWT.PUSH);
save.setText ("Save");
save.setToolTipText("Saves to the previously selected file.");
save.addListener (SWT.Selection, event -> saveToFile (false));
- parent.addListener (SWT.Resize, e -> layout ());
+ save.setLayoutData(new GridData(SWT.FILL, SWT.NONE, false, false));
stackTrace.setSelection (false);
- text.setVisible (false);
- layout();
}
private void toggleEnableTracking() {
@@ -118,33 +136,30 @@ private void toggleEnableTracking() {
}
void refreshLabel () {
- int cursors = 0, fonts = 0, gcs = 0, images = 0;
- int paths = 0, patterns = 0, regions = 0, textLayouts = 0, transforms= 0;
- for (Object object : objects) {
- if (object instanceof Cursor) cursors++;
- if (object instanceof Font) fonts++;
- if (object instanceof GC) gcs++;
- if (object instanceof Image) images++;
- if (object instanceof Path) paths++;
- if (object instanceof Pattern) patterns++;
- if (object instanceof Region) regions++;
- if (object instanceof TextLayout) textLayouts++;
- if (object instanceof Transform) transforms++;
- }
- String string = "";
- if (cursors != 0) string += cursors + " Cursor(s)\n";
- if (fonts != 0) string += fonts + " Font(s)\n";
- if (gcs != 0) string += gcs + " GC(s)\n";
- if (images != 0) string += images + " Image(s)\n";
- if (paths != 0) string += paths + " Paths(s)\n";
- if (patterns != 0) string += patterns + " Pattern(s)\n";
- if (regions != 0) string += regions + " Region(s)\n";
- if (textLayouts != 0) string += textLayouts + " TextLayout(s)\n";
- if (transforms != 0) string += transforms + " Transform(s)\n";
- if (string.length () != 0) {
- string = string.substring (0, string.length () - 1);
+ Map<String, Long> deleted = oldObjects.stream().collect(
+ Collectors.groupingBy(o -> o.object.getClass().getSimpleName(), Collectors.counting()));
+ Map<String, Long> created = objects.stream().collect(
+ Collectors.groupingBy(o -> o.object.getClass().getSimpleName(), Collectors.counting()));
+ StringBuilder sb = new StringBuilder();
+ Stream.concat(deleted.keySet().stream(), created.keySet().stream()).distinct().sorted().
+ forEach(type -> addCounts(sb, type, deleted.get(type), created.get(type)));
+ label.setText (sb.length() > 0 ? sb.toString() : "0 object(s)");
+ canvas.getParent().layout();
+}
+
+void addCounts (StringBuilder string, String type, Long deleted, Long created) {
+ if (deleted != null || created != null) {
+ if (deleted != null) {
+ string.append("-" + deleted);
+ if (created != null) {
+ string.append(" / ");
+ }
+ }
+ if (created != null) {
+ string.append(created);
+ }
+ string.append(" " + type + "(s)\n");
}
- label.setText (string);
}
void refreshDifference () {
@@ -160,50 +175,32 @@ void refreshDifference () {
toggleEnableTracking();
}
}
- int size = 0;
- for (int i = 0; i < info.objects.length; i++) {
- if (!(info.objects[i] instanceof Color)) {
- size++;
- }
- }
- Object [] newObjects = new Object[size];
- Error [] newErrors = new Error[size];
- for (int i = 0, out_i = 0; i < info.objects.length; i++) {
- // Bug 563018: Colors don't require disposal, so exclude
- // them from the list of allocated objects.
- if (!(info.objects[i] instanceof Color)) {
- newObjects[out_i] = info.objects[i];
- newErrors[out_i] = info.errors[i];
- out_i++;
- }
- }
- Object [] diffObjects = new Object [newObjects.length];
- Error [] diffErrors = new Error [newErrors.length];
- int count = 0;
- for (int i=0; i<newObjects.length; i++) {
- int index = 0;
- while (index < oldObjects.length) {
- if (newObjects [i] == oldObjects [index]) break;
- index++;
- }
- if (index == oldObjects.length) {
- diffObjects [count] = newObjects [i];
- diffErrors [count] = newErrors [i];
- count++;
+
+ oldObjects = new ArrayList<> (objects);
+ objects.clear ();
+ for (int i=0; i<info.objects.length; i++) {
+ boolean found = false;
+ Iterator<ObjectWithError> oldObject = oldObjects.iterator ();
+ if (!(info.objects [i] instanceof Color)) {
+ // Bug 563018: Colors don't require disposal, so exclude them from the list of allocated objects.
+ while (oldObject.hasNext () && !found) {
+ if (info.objects [i] == oldObject.next ().object) {
+ oldObject.remove ();
+ found = true;
+ }
+ }
+ if (!found) {
+ objects.add (new ObjectWithError (info.objects [i], info.errors[i]));
+ }
}
}
- objects = new Object [count];
- errors = new Error [count];
- System.arraycopy (diffObjects, 0, objects, 0, count);
- System.arraycopy (diffErrors, 0, errors, 0, count);
list.removeAll ();
text.setText ("");
canvas.redraw ();
- for (Object object : objects) {
- list.add (object.toString());
+ for (ObjectWithError object : objects) {
+ list.add (object.object.toString());
}
refreshLabel ();
- layout ();
}
private void saveToFile(boolean prompt) {
@@ -236,13 +233,14 @@ private void saveToFile(boolean prompt) {
fileName = String.format("%s_%03d", fileName, fileCount++);
}
try (PrintWriter file = new PrintWriter(new FileOutputStream(fileName))) {
-
- for (int i = 0; i < errors.length; i++) {
- Object object = objects[i];
- Error error = errors[i];
+
+ int i = 0;
+ for (ObjectWithError o : objects) {
+ Object object = o.object;
+ Error error = o.error;
file.print(object.toString());
if (saveImages) {
- String suffix = String.format("%05d.png", i);
+ String suffix = String.format("%05d.png", i++);
String pngName = String.format("%s_%s", fileName, suffix);
Image image = new Image(saveAs.getDisplay(), 100, 100);
try {
@@ -278,7 +276,7 @@ private void saveToFile(boolean prompt) {
void toggleStackTrace () {
refreshObject ();
- layout ();
+ canvas.getParent().layout ();
}
void paintCanvas (Event event) {
@@ -286,7 +284,7 @@ void paintCanvas (Event event) {
int index = list.getSelectionIndex ();
if (index == -1) return;
GC gc = event.gc;
- Object object = objects [index];
+ Object object = objects.get(index).object;
draw(gc, object);
}
@@ -357,60 +355,46 @@ void refreshObject () {
int index = list.getSelectionIndex ();
if (index == -1) return;
if (stackTrace.getSelection ()) {
- ByteArrayOutputStream stream = new ByteArrayOutputStream ();
- PrintStream s = new PrintStream (stream);
- errors [index].printStackTrace (s);
- text.setText (stream.toString ());
- text.setVisible (true);
- canvas.setVisible (false);
+ text.setText (objects.get(index).getStack());
+ setVisible(text, true);
+ setVisible(canvas, false);
+ canvas.getParent().layout();
} else {
- canvas.setVisible (true);
- text.setVisible (false);
+ setVisible(canvas, true);
+ setVisible(text, false);
canvas.redraw ();
}
}
+private void setVisible(Control control, boolean visible) {
+ control.setVisible(visible);
+ ((GridData)control.getLayoutData()).exclude = !visible;
+}
+
void refreshAll () {
- oldObjects = new Object [0];
- oldErrors = new Error [0];
+ objects.clear();
refreshDifference ();
- oldObjects = objects;
- oldErrors = errors;
+ oldObjects = new ArrayList<>(objects);
}
-void layout () {
- Composite parent = canvas.getParent();
- Rectangle rect = parent.getClientArea ();
- int width = 0;
- String [] items = list.getItems ();
- GC gc = new GC (list);
- for (int i=0; i<objects.length; i++) {
- width = Math.max (width, gc.stringExtent (items [i]).x);
+private static final class ObjectWithError {
+ final Object object;
+ final Error error;
+ String stack;
+
+ ObjectWithError(Object o, Error e) {
+ this.object = o;
+ this.error = e;
+ }
+
+ String getStack() {
+ if (stack == null) {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ PrintStream s = new PrintStream(stream);
+ error.printStackTrace(s);
+ stack = stream.toString();
+ }
+ return stack;
}
- gc.dispose ();
- Point enableTrackingSize = enableTracking.computeSize (SWT.DEFAULT, SWT.DEFAULT);
- Point snapshotSize = snapshot.computeSize (SWT.DEFAULT, SWT.DEFAULT);
- Point diffSize = diff.computeSize (SWT.DEFAULT, SWT.DEFAULT);
- Point stackSize = stackTrace.computeSize (SWT.DEFAULT, SWT.DEFAULT);
- Point labelSize = label.computeSize (SWT.DEFAULT, SWT.DEFAULT);
- Point saveAsSize = saveAs.computeSize (SWT.DEFAULT, SWT.DEFAULT);
- Point saveSize = save.computeSize (SWT.DEFAULT, SWT.DEFAULT);
- width = Math.max (enableTrackingSize.x, width);
- width = Math.max (snapshotSize.x, Math.max (diffSize.x, Math.max (stackSize.x, width)));
- width = Math.max (saveAsSize.x, Math.max (saveSize.x, width));
- width = Math.max (labelSize.x, list.computeSize (width, SWT.DEFAULT).x);
- width = Math.max (64, width);
- enableTracking.setBounds (0, 0, width, enableTrackingSize.y);
- snapshot.setBounds (0, enableTrackingSize.y, width, snapshotSize.y);
- diff.setBounds (0, enableTrackingSize.y + snapshotSize.y, width, diffSize.y);
- stackTrace.setBounds (0, enableTrackingSize.y + snapshotSize.y + diffSize.y, width, stackSize.y);
- label.setBounds (0, rect.height - saveSize.y - saveAsSize.y - labelSize.y, width, labelSize.y);
- saveAs.setBounds (0, rect.height - saveSize.y - saveAsSize.y, width, saveAsSize.y);
- save.setBounds (0, rect.height - saveSize.y, width, saveSize.y);
- int height = enableTrackingSize.y + snapshotSize.y + diffSize.y + stackSize.y;
- list.setBounds (0, height, width, rect.height - height - labelSize.y - saveAsSize.y -saveSize.y);
- text.setBounds (width, 0, rect.width - width, rect.height);
- canvas.setBounds (width, 0, rect.width - width, rect.height);
}
-
}

Back to the top