|
24 | 24 | */
|
25 | 25 | package org.graalvm.visualvm.heapviewer.utils;
|
26 | 26 |
|
| 27 | +import java.util.List; |
27 | 28 | import java.util.Map;
|
28 | 29 | import java.util.WeakHashMap;
|
29 | 30 | import javax.swing.SwingUtilities;
|
30 | 31 | import org.graalvm.visualvm.heapviewer.HeapFragment;
|
31 | 32 | import org.graalvm.visualvm.lib.jfluid.heap.Heap;
|
32 | 33 | import org.graalvm.visualvm.lib.jfluid.heap.HeapProgress;
|
33 | 34 | import org.graalvm.visualvm.lib.jfluid.heap.Instance;
|
| 35 | +import org.graalvm.visualvm.lib.jfluid.heap.JavaClass; |
34 | 36 | import org.netbeans.api.progress.ProgressHandle;
|
35 | 37 | import org.openide.util.NbBundle;
|
36 | 38 |
|
|
40 | 42 | */
|
41 | 43 | @NbBundle.Messages({
|
42 | 44 | "HeapOperations_ComputingReferences=Computing References...",
|
43 |
| - "HeapOperations_ComputingGCRoots=Computing GC Roots..." |
| 45 | + "HeapOperations_ComputingGCRoots=Computing GC Roots...", |
| 46 | + "HeapOperations_ComputingRetainedSizes=Computing Retained Sizes..." |
44 | 47 | })
|
45 | 48 | public final class HeapOperations {
|
46 | 49 |
|
@@ -71,6 +74,10 @@ public static void initializeGCRoots(Heap heap) throws InterruptedException {
|
71 | 74 | get(heap).initializeGCRootsImpl(heap);
|
72 | 75 | }
|
73 | 76 |
|
| 77 | + public static void initializeRetainedSizes(Heap heap) throws InterruptedException { |
| 78 | + get(heap).initializeRetainedSizesImpl(heap); |
| 79 | + } |
| 80 | + |
74 | 81 |
|
75 | 82 | // --- References ----------------------------------------------------------
|
76 | 83 |
|
@@ -171,4 +178,55 @@ public void run() {
|
171 | 178 | _gcrootsComputer.join();
|
172 | 179 | }
|
173 | 180 |
|
| 181 | + |
| 182 | + // --- GC Roots ------------------------------------------------------------ |
| 183 | + |
| 184 | + private static boolean retainedInitialized; |
| 185 | + private static volatile Thread retainedComputer; |
| 186 | + |
| 187 | + private void initializeRetainedSizesImpl(Heap heap) throws InterruptedException { |
| 188 | + initializeGCRootsImpl(heap); |
| 189 | + |
| 190 | + Thread _retainedComputer; |
| 191 | + |
| 192 | + synchronized (this) { |
| 193 | + if (retainedInitialized) return; |
| 194 | + |
| 195 | + if (retainedComputer == null) { |
| 196 | + Runnable workerR = new Runnable() { |
| 197 | + public void run() { |
| 198 | + ProgressHandle pHandle = null; |
| 199 | + |
| 200 | + try { |
| 201 | + pHandle = ProgressHandle.createHandle(Bundle.HeapOperations_ComputingRetainedSizes()); |
| 202 | + pHandle.setInitialDelay(1000); |
| 203 | + pHandle.start(); |
| 204 | + |
| 205 | + HeapFragment.setProgress(pHandle, 0); |
| 206 | + |
| 207 | + List<JavaClass> classes = heap.getAllClasses(); |
| 208 | + if (!classes.isEmpty()) classes.get(0).getRetainedSizeByClass(); |
| 209 | + } finally { |
| 210 | + if (pHandle != null) pHandle.finish(); |
| 211 | + } |
| 212 | + |
| 213 | + synchronized (this) { |
| 214 | + retainedInitialized = false; |
| 215 | + retainedComputer = null; |
| 216 | + } |
| 217 | + } |
| 218 | + }; |
| 219 | + retainedComputer = new Thread(workerR, "Retained Sizes Computer"); // NO18N |
| 220 | + _retainedComputer = retainedComputer; // NOTE: must be assigned before starting the thread which eventually nulls the retainedComputer! |
| 221 | + retainedComputer.start(); |
| 222 | + } else { |
| 223 | + _retainedComputer = retainedComputer; |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | + assert !SwingUtilities.isEventDispatchThread(); |
| 228 | + |
| 229 | + _retainedComputer.join(); |
| 230 | + } |
| 231 | + |
174 | 232 | }
|
0 commit comments