25
25
26
26
package org .graalvm .visualvm .heapviewer .java .impl ;
27
27
28
+ import java .awt .BorderLayout ;
29
+ import java .awt .GridBagConstraints ;
30
+ import java .awt .GridBagLayout ;
31
+ import java .awt .Insets ;
28
32
import java .awt .event .ActionEvent ;
29
33
import java .util .Arrays ;
30
34
import java .util .HashMap ;
35
39
import java .util .Objects ;
36
40
import java .util .Set ;
37
41
import javax .swing .ImageIcon ;
42
+ import javax .swing .JButton ;
38
43
import javax .swing .JCheckBoxMenuItem ;
39
44
import javax .swing .JComponent ;
45
+ import javax .swing .JPanel ;
40
46
import javax .swing .JPopupMenu ;
41
47
import javax .swing .SortOrder ;
42
48
import javax .swing .SwingUtilities ;
57
63
import org .graalvm .visualvm .heapviewer .model .Progress ;
58
64
import org .graalvm .visualvm .heapviewer .model .RootNode ;
59
65
import org .graalvm .visualvm .heapviewer .model .TextNode ;
66
+ import org .graalvm .visualvm .heapviewer .swing .LinkButton ;
60
67
import org .graalvm .visualvm .heapviewer .ui .HeapViewPlugin ;
61
68
import org .graalvm .visualvm .heapviewer .ui .HeapViewerActions ;
62
69
import org .graalvm .visualvm .heapviewer .ui .HeapViewerRenderer ;
71
78
import org .graalvm .visualvm .heapviewer .utils .ProgressIterator ;
72
79
import org .graalvm .visualvm .lib .jfluid .heap .JavaClass ;
73
80
import org .graalvm .visualvm .lib .jfluid .heap .Value ;
81
+ import org .graalvm .visualvm .lib .ui .UIUtils ;
74
82
import org .graalvm .visualvm .lib .ui .swing .renderer .LabelRenderer ;
75
83
import org .openide .util .Lookup ;
76
84
import org .openide .util .NbBundle ;
85
93
"JavaReferencesPlugin_Name=References" ,
86
94
"JavaReferencesPlugin_Description=References" ,
87
95
"JavaReferencesPlugin_NoReferences=<no references>" ,
88
- "JavaReferencesPlugin_NoReferencesFiltered=<merged references disabled>" ,
96
+ // "JavaReferencesPlugin_NoReferencesFiltered=<merged references disabled>",
89
97
"JavaReferencesPlugin_NoSelection=<no class or instance selected>" ,
90
98
"JavaReferencesPlugin_MoreNodes=<another {0} references left>" ,
91
99
"JavaReferencesPlugin_SamplesContainer=<sample {0} references>" ,
92
100
"JavaReferencesPlugin_NodesContainer=<references {0}-{1}>" ,
93
101
"JavaReferencesPlugin_IMoreNodes=<another {0} instances left>" ,
94
102
"JavaReferencesPlugin_ISamplesContainer=<sample {0} instances>" ,
95
103
"JavaReferencesPlugin_INodesContainer=<instances {0}-{1}>" ,
96
- "JavaReferencesPlugin_MenuShowMergedReferences=Show Merged References" ,
104
+ "JavaReferencesPlugin_ComputeMergedReferencesLbl=Compute Merged References" ,
105
+ "JavaReferencesPlugin_ComputeMergedReferencesTtp=Compute merged references for the selected class" ,
106
+ "JavaReferencesPlugin_AutoComputeMergedReferencesLbl=Compute Merged References Automatically" ,
107
+ "JavaReferencesPlugin_AutoComputeMergedReferencesTtp=Compute merged references automatically for each selected class" ,
97
108
"JavaReferencesPlugin_MenuShowLogicalReferences=Show Logical References"
98
109
})
99
110
class JavaReferencesPlugin extends HeapViewPlugin {
100
111
101
112
private static final TreeTableView .ColumnConfiguration CCONF_CLASS = new TreeTableView .ColumnConfiguration (DataType .COUNT , null , DataType .COUNT , SortOrder .DESCENDING , Boolean .FALSE );
102
113
private static final TreeTableView .ColumnConfiguration CCONF_INSTANCE = new TreeTableView .ColumnConfiguration (null , DataType .COUNT , DataType .NAME , SortOrder .UNSORTED , null );
103
114
104
- private static final String KEY_MERGED_REFERENCES = "mergedReferences " ; // NOI18N
115
+ private static final String KEY_MERGED_REFERENCES = "autoMergedReferences " ; // NOI18N
105
116
private static final String KEY_LOGICAL_REFERENCES = "logicalkReferences" ; // NOI18N
106
117
107
- private volatile boolean mergedReferences = readItem (KEY_MERGED_REFERENCES , true );
118
+ private volatile boolean mergedReferences = readItem (KEY_MERGED_REFERENCES , false );
108
119
private volatile boolean logicalReferences = readItem (KEY_LOGICAL_REFERENCES , true );
109
120
110
121
private final Heap heap ;
111
122
private HeapViewerNode selected ;
112
123
124
+ private volatile boolean mergedRequest ;
125
+
113
126
private final TreeTableView objectsView ;
114
127
115
128
@@ -128,6 +141,8 @@ public JavaReferencesPlugin(HeapContext context, HeapViewerActions actions, fina
128
141
};
129
142
objectsView = new TreeTableView ("java_objects_references" , context , actions , columns ) { // NOI18N
130
143
protected HeapViewerNode [] computeData (RootNode root , Heap heap , String viewID , HeapViewerNodeFilter viewFilter , List <DataType > dataTypes , List <SortOrder > sortOrders , Progress progress ) throws InterruptedException {
144
+ if (mergedRequest ) return HeapViewerNode .NO_NODES ;
145
+
131
146
HeapViewerNode _selected ;
132
147
synchronized (objectsView ) { _selected = selected ; }
133
148
@@ -137,14 +152,16 @@ protected HeapViewerNode[] computeData(RootNode root, Heap heap, String viewID,
137
152
if (wrapper != null ) {
138
153
SwingUtilities .invokeLater (new Runnable () {
139
154
public void run () {
140
- if (!mergedReferences && !CCONF_INSTANCE .equals (objectsView .getCurrentColumnConfiguration ()))
141
- objectsView .configureColumns (CCONF_INSTANCE );
142
- else if (mergedReferences && !CCONF_CLASS .equals (objectsView .getCurrentColumnConfiguration ()))
155
+ // if (!mergedReferences && !CCONF_INSTANCE.equals(objectsView.getCurrentColumnConfiguration()))
156
+ // objectsView.configureColumns(CCONF_INSTANCE);
157
+ // else if (mergedReferences && !CCONF_CLASS.equals(objectsView.getCurrentColumnConfiguration()))
158
+ // objectsView.configureColumns(CCONF_CLASS);
159
+ if (!CCONF_CLASS .equals (objectsView .getCurrentColumnConfiguration ()))
143
160
objectsView .configureColumns (CCONF_CLASS );
144
161
}
145
162
});
146
163
147
- if (!mergedReferences ) return new HeapViewerNode [] { new TextNode (Bundle .JavaReferencesPlugin_NoReferencesFiltered ()) };
164
+ // if (!mergedReferences) return new HeapViewerNode[] { new TextNode(Bundle.JavaReferencesPlugin_NoReferencesFiltered()) };
148
165
149
166
return computeInstancesReferences (wrapper , root , heap , viewID , null , dataTypes , sortOrders , progress );
150
167
} else {
@@ -170,15 +187,18 @@ public void run() {
170
187
protected void populatePopup (HeapViewerNode node , JPopupMenu popup ) {
171
188
if (popup .getComponentCount () > 0 ) popup .addSeparator ();
172
189
173
- popup .add (new JCheckBoxMenuItem (Bundle .JavaReferencesPlugin_MenuShowMergedReferences (), mergedReferences ) {
190
+ popup .add (new JCheckBoxMenuItem (Bundle .JavaReferencesPlugin_AutoComputeMergedReferencesLbl (), mergedReferences ) {
174
191
@ Override
175
192
protected void fireActionPerformed (ActionEvent event ) {
176
193
SwingUtilities .invokeLater (new Runnable () {
177
194
@ Override
178
195
public void run () {
179
196
mergedReferences = isSelected ();
180
197
storeItem (KEY_MERGED_REFERENCES , mergedReferences );
181
- reloadView ();
198
+ if (CCONF_CLASS .equals (objectsView .getCurrentColumnConfiguration ())) { // only update view for class selection
199
+ if (!mergedReferences ) showMergedView ();
200
+ reloadView (); // reload even if !mergedReferences to release the currently computed references
201
+ }
182
202
}
183
203
});
184
204
}
@@ -192,17 +212,100 @@ protected void fireActionPerformed(ActionEvent event) {
192
212
public void run () {
193
213
logicalReferences = isSelected ();
194
214
storeItem (KEY_LOGICAL_REFERENCES , logicalReferences );
195
- reloadView ();
215
+ if (CCONF_CLASS .equals (objectsView .getCurrentColumnConfiguration ())) { // only update view for class selection
216
+ reloadView ();
217
+ }
196
218
}
197
219
});
198
220
}
199
221
});
200
222
}
201
223
};
202
224
}
225
+
226
+
227
+ private JComponent component ;
228
+
229
+ private void showObjectsView () {
230
+ JComponent c = objectsView .getComponent ();
231
+ if (c .isVisible ()) return ;
232
+
233
+ c .setVisible (true );
234
+
235
+ component .removeAll ();
236
+ component .add (c , BorderLayout .CENTER );
237
+
238
+ mergedRequest = false ;
239
+
240
+ component .invalidate ();
241
+ component .revalidate ();
242
+ component .repaint ();
243
+ }
244
+
245
+ private void showMergedView () {
246
+ JComponent c = objectsView .getComponent ();
247
+ if (!c .isVisible ()) return ;
248
+
249
+ c .setVisible (false );
250
+
251
+ component .removeAll ();
252
+
253
+ JButton jb = new JButton (Bundle .JavaReferencesPlugin_ComputeMergedReferencesLbl (), Icons .getIcon (ProfilerIcons .NODE_REVERSE )) {
254
+ protected void fireActionPerformed (ActionEvent e ) {
255
+ showObjectsView ();
256
+ objectsView .reloadView ();
257
+ }
258
+ };
259
+ jb .setIconTextGap (jb .getIconTextGap () + 2 );
260
+ jb .setToolTipText (Bundle .JavaReferencesPlugin_ComputeMergedReferencesTtp ());
261
+ Insets margin = jb .getMargin ();
262
+ if (margin != null ) jb .setMargin (new Insets (margin .top + 3 , margin .left + 3 , margin .bottom + 3 , margin .right + 3 ));
263
+
264
+
265
+ LinkButton lb = new LinkButton (Bundle .JavaReferencesPlugin_AutoComputeMergedReferencesLbl ()) {
266
+ protected void fireActionPerformed (ActionEvent e ) {
267
+ showObjectsView ();
268
+ mergedReferences = true ;
269
+ storeItem (KEY_MERGED_REFERENCES , mergedReferences );
270
+ objectsView .reloadView ();
271
+ }
272
+ };
273
+ lb .setToolTipText (Bundle .JavaReferencesPlugin_AutoComputeMergedReferencesTtp ());
274
+
275
+
276
+ JPanel p = new JPanel (new GridBagLayout ());
277
+ p .setOpaque (false );
278
+ GridBagConstraints g ;
279
+
280
+ g = new GridBagConstraints ();
281
+ g .fill = GridBagConstraints .HORIZONTAL ;
282
+ g .gridy = 0 ;
283
+ p .add (jb , g );
284
+
285
+ g = new GridBagConstraints ();
286
+ g .fill = GridBagConstraints .HORIZONTAL ;
287
+ g .gridy = 1 ;
288
+ g .insets = new Insets (10 , 0 , 0 , 0 );
289
+ p .add (lb , g );
290
+
291
+ component .add (p );
292
+
293
+ mergedRequest = true ;
294
+
295
+ component .invalidate ();
296
+ component .revalidate ();
297
+ component .repaint ();
298
+ }
203
299
204
300
protected JComponent createComponent () {
205
- return objectsView .getComponent ();
301
+ component = new JPanel (new BorderLayout ());
302
+ component .setOpaque (true );
303
+ component .setBackground (UIUtils .getProfilerResultsBackground ());
304
+
305
+ objectsView .getComponent ().setVisible (false ); // force init in showObjectsView()
306
+ showObjectsView ();
307
+
308
+ return component ;
206
309
}
207
310
208
311
@@ -251,6 +354,8 @@ private HeapViewerNode[] computeInstancesReferences(final InstancesWrapper insta
251
354
progress .finish ();
252
355
}
253
356
357
+ if (values .isEmpty ()) return new HeapViewerNode [] { new TextNode (Bundle .JavaReferencesPlugin_NoReferences ()) };
358
+
254
359
NodesComputer <Map .Entry <Long , Integer >> computer = new NodesComputer <Map .Entry <Long , Integer >>(values .size (), UIThresholds .MAX_CLASS_INSTANCES ) {
255
360
protected boolean sorts (DataType dataType ) {
256
361
return true ;
@@ -289,6 +394,9 @@ protected void nodeSelected(HeapViewerNode node, boolean adjusting) {
289
394
selected = node ;
290
395
}
291
396
397
+ if (selected != null && !mergedReferences && HeapViewerNode .getValue (selected , DataType .INSTANCES_WRAPPER , heap ) != null ) showMergedView ();
398
+ else showObjectsView ();
399
+
292
400
objectsView .reloadView ();
293
401
}
294
402
0 commit comments