• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package art;
18 
19 import java.io.BufferedReader;
20 import java.io.File;
21 import java.io.FileReader;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.concurrent.CountDownLatch;
28 
29 public class Test913 {
run()30   public static void run() throws Exception {
31     doTest();
32 
33     // Use a countdown latch for synchronization, as join() will introduce more roots.
34     final CountDownLatch cdl1 = new CountDownLatch(1);
35 
36     // Run the follow-references tests on a dedicated thread so we know the specific Thread type.
37     Thread t = new Thread() {
38       @Override
39       public void run() {
40         try {
41           Test913.runFollowReferences();
42         } catch (Exception e) {
43           throw new RuntimeException(e);
44         }
45         cdl1.countDown();
46       }
47     };
48     t.start();
49     cdl1.await();
50 
51     doExtensionTests();
52   }
53 
runFollowReferences()54   public static void runFollowReferences() throws Exception {
55     new TestConfig().doFollowReferencesTest();
56 
57     Runtime.getRuntime().gc();
58     Runtime.getRuntime().gc();
59 
60     new TestConfig(null, 0, 1, -1).doFollowReferencesTest();
61 
62     Runtime.getRuntime().gc();
63     Runtime.getRuntime().gc();
64 
65     new TestConfig(null, 0, Integer.MAX_VALUE, 1).doFollowReferencesTest();
66 
67     Runtime.getRuntime().gc();
68     Runtime.getRuntime().gc();
69 
70     doStringTest();
71 
72     Runtime.getRuntime().gc();
73     Runtime.getRuntime().gc();
74 
75     doPrimitiveArrayTest();
76     doPrimitiveFieldTest();
77 
78     Runtime.getRuntime().gc();
79     Runtime.getRuntime().gc();
80 
81     // Test klass filter.
82     System.out.println("--- klass ---");
83     new TestConfig(A.class, 0).doFollowReferencesTest();
84 
85     // Test heap filter.
86     System.out.println("--- heap_filter ---");
87     System.out.println("---- tagged objects");
88     new TestConfig(null, 0x4).doFollowReferencesTest();
89     System.out.println("---- untagged objects");
90     new TestConfig(null, 0x8).doFollowReferencesTest();
91     System.out.println("---- tagged classes");
92     new TestConfig(null, 0x10).doFollowReferencesTest();
93     System.out.println("---- untagged classes");
94     new TestConfig(null, 0x20).doFollowReferencesTest();
95   }
96 
doTest()97   public static void doTest() throws Exception {
98     setupGcCallback();
99 
100     enableGcTracking(true);
101     runGc();
102     enableGcTracking(false);
103   }
104 
doStringTest()105   public static void doStringTest() throws Exception {
106     final String str = new String("HelloWorld");
107     final String str2 = new String("");
108     Object o = new Object() {
109       String s = str;
110       String s2 = str2;
111     };
112 
113     setTag(str, 1);
114     setTag(str2, 2);
115     System.out.println(Arrays.toString(followReferencesString(o)));
116     System.out.println(getTag(str));
117     System.out.println(getTag(str2));
118   }
119 
doPrimitiveArrayTest()120   public static void doPrimitiveArrayTest() throws Exception {
121     final boolean[] zArray = new boolean[] { false, true };
122     setTag(zArray, 1);
123 
124     final byte[] bArray = new byte[] { 1, 2, 3 };
125     setTag(bArray, 2);
126 
127     final char[] cArray = new char[] { 'A', 'Z' };
128     setTag(cArray, 3);
129 
130     final short[] sArray = new short[] { 1, 2, 3 };
131     setTag(sArray, 4);
132 
133     final int[] iArray = new int[] { 1, 2, 3 };
134     setTag(iArray, 5);
135 
136     final float[] fArray = new float[] { 0.0f, 1.0f };
137     setTag(fArray, 6);
138 
139     final long[] lArray = new long[] { 1, 2, 3 };
140     setTag(lArray, 7);
141 
142     final double[] dArray = new double[] { 0.0, 1.0 };
143     setTag(dArray, 8);
144 
145     Object o = new Object() {
146       Object z = zArray;
147       Object b = bArray;
148       Object c = cArray;
149       Object s = sArray;
150       Object i = iArray;
151       Object f = fArray;
152       Object l = lArray;
153       Object d = dArray;
154     };
155 
156     System.out.println(followReferencesPrimitiveArray(o));
157     System.out.print(getTag(zArray));
158     System.out.print(getTag(bArray));
159     System.out.print(getTag(cArray));
160     System.out.print(getTag(sArray));
161     System.out.print(getTag(iArray));
162     System.out.print(getTag(fArray));
163     System.out.print(getTag(lArray));
164     System.out.println(getTag(dArray));
165   }
166 
doPrimitiveFieldTest()167   public static void doPrimitiveFieldTest() throws Exception {
168     // Force GCs to clean up dirt.
169     Runtime.getRuntime().gc();
170     Runtime.getRuntime().gc();
171 
172     doTestPrimitiveFieldsClasses();
173 
174     doTestPrimitiveFieldsIntegral();
175 
176     // Force GCs to clean up dirt.
177     Runtime.getRuntime().gc();
178     Runtime.getRuntime().gc();
179 
180     doTestPrimitiveFieldsFloat();
181 
182     // Force GCs to clean up dirt.
183     Runtime.getRuntime().gc();
184     Runtime.getRuntime().gc();
185   }
186 
doTestPrimitiveFieldsClasses()187   private static void doTestPrimitiveFieldsClasses() {
188     setTag(IntObject.class, 10000);
189     System.out.println(followReferencesPrimitiveFields(IntObject.class));
190     System.out.println(getTag(IntObject.class));
191     setTag(IntObject.class, 0);
192 
193     setTag(FloatObject.class, 10000);
194     System.out.println(followReferencesPrimitiveFields(FloatObject.class));
195     System.out.println(getTag(FloatObject.class));
196     setTag(FloatObject.class, 0);
197 
198     setTag(Inf1.class, 10000);
199     System.out.println(followReferencesPrimitiveFields(Inf1.class));
200     System.out.println(getTag(Inf1.class));
201     setTag(Inf1.class, 0);
202 
203     setTag(Inf2.class, 10000);
204     System.out.println(followReferencesPrimitiveFields(Inf2.class));
205     System.out.println(getTag(Inf2.class));
206     setTag(Inf2.class, 0);
207   }
208 
doTestPrimitiveFieldsIntegral()209   private static void doTestPrimitiveFieldsIntegral() {
210     IntObject intObject = new IntObject();
211     setTag(intObject, 10000);
212     System.out.println(followReferencesPrimitiveFields(intObject));
213     System.out.println(getTag(intObject));
214   }
215 
doTestPrimitiveFieldsFloat()216   private static void doTestPrimitiveFieldsFloat() {
217     FloatObject floatObject = new FloatObject();
218     setTag(floatObject, 10000);
219     System.out.println(followReferencesPrimitiveFields(floatObject));
220     System.out.println(getTag(floatObject));
221   }
222 
223   static ArrayList<Object> extensionTestHolder;
224 
doExtensionTests()225   private static void doExtensionTests() {
226     checkForExtensionApis();
227 
228     extensionTestHolder = new ArrayList<>();
229     System.out.println();
230 
231     try {
232       getHeapName(-1);
233       System.out.println("Expected failure for -1");
234     } catch (Exception e) {
235     }
236     System.out.println(getHeapName(0));
237     System.out.println(getHeapName(1));
238     System.out.println(getHeapName(2));
239     System.out.println(getHeapName(3));
240     try {
241       getHeapName(4);
242       System.out.println("Expected failure for -1");
243     } catch (Exception e) {
244     }
245 
246     System.out.println();
247 
248     setTag(Object.class, 100000);
249     int objectClassHeapId = getObjectHeapId(100000);
250     int objClassExpectedHeapId = hasImage() ? 1 : 3;
251     if (objectClassHeapId != objClassExpectedHeapId) {
252       throw new RuntimeException("Expected object class in heap " + objClassExpectedHeapId +
253           " but received " + objectClassHeapId);
254     }
255 
256     A a = new A();
257     extensionTestHolder.add(a);
258     setTag(a, 100001);
259     System.out.println(getObjectHeapId(100001));
260 
261     checkGetObjectHeapIdInCallback(100000, objClassExpectedHeapId);
262     checkGetObjectHeapIdInCallback(100001, 3);
263 
264     long baseTag = 30000000;
265     setTag(Object.class, baseTag + objClassExpectedHeapId);
266     setTag(Class.class, baseTag + objClassExpectedHeapId);
267     Object o = new Object();
268     extensionTestHolder.add(o);
269     setTag(o, baseTag + 3);
270 
271     iterateThroughHeapExt();
272 
273     extensionTestHolder = null;
274   }
275 
runGc()276   private static void runGc() {
277     clearStats();
278     forceGarbageCollection();
279     printStats();
280   }
281 
clearStats()282   private static void clearStats() {
283     getGcStarts();
284     getGcFinishes();
285   }
286 
printStats()287   private static void printStats() {
288     System.out.println("---");
289     int s = getGcStarts();
290     int f = getGcFinishes();
291     System.out.println((s > 0) + " " + (f > 0));
292   }
293 
hasImage()294   private static boolean hasImage() {
295     try {
296       int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
297       BufferedReader reader = new BufferedReader(new FileReader("/proc/" + pid + "/maps"));
298       String line;
299       while ((line = reader.readLine()) != null) {
300         if (line.endsWith(".art")) {
301           reader.close();
302           return true;
303         }
304       }
305       reader.close();
306       return false;
307     } catch (Exception e) {
308       throw new RuntimeException(e);
309     }
310   }
311 
312   private static class TestConfig {
313     private Class<?> klass = null;
314     private int heapFilter = 0;
315     private int stopAfter = Integer.MAX_VALUE;
316     private int followSet = -1;
317 
TestConfig()318     public TestConfig() {
319     }
TestConfig(Class<?> klass, int heapFilter)320     public TestConfig(Class<?> klass, int heapFilter) {
321       this.klass = klass;
322       this.heapFilter = heapFilter;
323     }
TestConfig(Class<?> klass, int heapFilter, int stopAfter, int followSet)324     public TestConfig(Class<?> klass, int heapFilter, int stopAfter, int followSet) {
325       this.klass = klass;
326       this.heapFilter = heapFilter;
327       this.stopAfter = stopAfter;
328       this.followSet = followSet;
329     }
330 
doFollowReferencesTest()331     public void doFollowReferencesTest() throws Exception {
332       // Force GCs to clean up dirt.
333       Runtime.getRuntime().gc();
334       Runtime.getRuntime().gc();
335 
336       setTag(Thread.currentThread(), 3000);
337 
338       {
339         ArrayList<Object> tmpStorage = new ArrayList<>();
340         doFollowReferencesTestNonRoot(tmpStorage);
341         tmpStorage = null;
342       }
343 
344       // Force GCs to clean up dirt.
345       Runtime.getRuntime().gc();
346       Runtime.getRuntime().gc();
347 
348       doFollowReferencesTestRoot();
349 
350       // Force GCs to clean up dirt.
351       Runtime.getRuntime().gc();
352       Runtime.getRuntime().gc();
353     }
354 
doFollowReferencesTestNonRoot(ArrayList<Object> tmpStorage)355     private void doFollowReferencesTestNonRoot(ArrayList<Object> tmpStorage) {
356       Verifier v = new Verifier();
357       tagClasses(v);
358       A a = createTree(v);
359       tmpStorage.add(a);
360       v.add("0@0", "1@1000");  // tmpStorage[0] --(array-element)--> a.
361 
362       doFollowReferencesTestImpl(null, stopAfter, followSet, null, v, null);
363       doFollowReferencesTestImpl(a.foo2, stopAfter, followSet, null, v, "3@1001");
364 
365       tmpStorage.clear();
366     }
367 
doFollowReferencesTestRoot()368     private void doFollowReferencesTestRoot() {
369       Verifier v = new Verifier();
370       tagClasses(v);
371       A a = createTree(v);
372 
373       doFollowReferencesTestImpl(null, stopAfter, followSet, a, v, null);
374       doFollowReferencesTestImpl(a.foo2, stopAfter, followSet, a, v, "3@1001");
375     }
376 
doFollowReferencesTestImpl(A root, int stopAfter, int followSet, Object asRoot, Verifier v, String additionalEnabled)377     private void doFollowReferencesTestImpl(A root, int stopAfter, int followSet,
378         Object asRoot, Verifier v, String additionalEnabled) {
379       String[] lines =
380           followReferences(heapFilter, klass, root, stopAfter, followSet, asRoot);
381 
382       v.process(lines, additionalEnabled, heapFilter != 0 || klass != null);
383     }
384 
tagClasses(Verifier v)385     private static void tagClasses(Verifier v) {
386       setTag(A.class, 1000);
387 
388       setTag(B.class, 1001);
389       v.add("1001@0", "1000@0");  // B.class --(superclass)--> A.class.
390 
391       setTag(C.class, 1002);
392       v.add("1002@0", "1001@0");  // C.class --(superclass)--> B.class.
393       v.add("1002@0", "2001@0");  // C.class --(interface)--> I2.class.
394 
395       setTag(I1.class, 2000);
396 
397       setTag(I2.class, 2001);
398       v.add("2001@0", "2000@0");  // I2.class --(interface)--> I1.class.
399     }
400 
createTree(Verifier v)401     private static A createTree(Verifier v) {
402       A aInst = new A();
403       setTag(aInst, 1);
404       String aInstStr = "1@1000";
405       String aClassStr = "1000@0";
406       v.add(aInstStr, aClassStr);  // A -->(class) --> A.class.
407 
408       A a2Inst = new A();
409       setTag(a2Inst, 2);
410       aInst.foo = a2Inst;
411       String a2InstStr = "2@1000";
412       v.add(a2InstStr, aClassStr);  // A2 -->(class) --> A.class.
413       v.add(aInstStr, a2InstStr);   // A -->(field) --> A2.
414 
415       B bInst = new B();
416       setTag(bInst, 3);
417       aInst.foo2 = bInst;
418       String bInstStr = "3@1001";
419       String bClassStr = "1001@0";
420       v.add(bInstStr, bClassStr);  // B -->(class) --> B.class.
421       v.add(aInstStr, bInstStr);   // A -->(field) --> B.
422 
423       A a3Inst = new A();
424       setTag(a3Inst, 4);
425       bInst.bar = a3Inst;
426       String a3InstStr = "4@1000";
427       v.add(a3InstStr, aClassStr);  // A3 -->(class) --> A.class.
428       v.add(bInstStr, a3InstStr);   // B -->(field) --> A3.
429 
430       C cInst = new C();
431       setTag(cInst, 5);
432       bInst.bar2 = cInst;
433       String cInstStr = "5@1000";
434       String cClassStr = "1002@0";
435       v.add(cInstStr, cClassStr);  // C -->(class) --> C.class.
436       v.add(bInstStr, cInstStr);   // B -->(field) --> C.
437 
438       A a4Inst = new A();
439       setTag(a4Inst, 6);
440       cInst.baz = a4Inst;
441       String a4InstStr = "6@1000";
442       v.add(a4InstStr, aClassStr);  // A4 -->(class) --> A.class.
443       v.add(cInstStr, a4InstStr);   // C -->(field) --> A4.
444 
445       cInst.baz2 = aInst;
446       v.add(cInstStr, aInstStr);  // C -->(field) --> A.
447 
448       A[] aArray = new A[2];
449       setTag(aArray, 500);
450       aArray[1] = a2Inst;
451       cInst.array = aArray;
452       String aArrayStr = "500@0";
453       v.add(cInstStr, aArrayStr);
454       v.add(aArrayStr, a2InstStr);
455 
456       return aInst;
457     }
458   }
459 
460   public static class A {
461     public A foo;
462     public A foo2;
463 
A()464     public A() {}
A(A a, A b)465     public A(A a, A b) {
466       foo = a;
467       foo2 = b;
468     }
469   }
470 
471   public static class B extends A {
472     public A bar;
473     public A bar2;
474 
B()475     public B() {}
B(A a, A b)476     public B(A a, A b) {
477       bar = a;
478       bar2 = b;
479     }
480   }
481 
482   public static interface I1 {
483     public final static int i1Field = 1;
484   }
485 
486   public static interface I2 extends I1 {
487     public final static int i2Field = 2;
488   }
489 
490   public static class C extends B implements I2 {
491     public A baz;
492     public A baz2;
493     public A[] array;
494 
C()495     public C() {}
C(A a, A b)496     public C(A a, A b) {
497       baz = a;
498       baz2 = b;
499     }
500   }
501 
502   private static interface Inf1 {
503     public final static int A = 1;
504   }
505 
506   private static interface Inf2 extends Inf1 {
507     public final static int B = 1;
508   }
509 
510   private static class IntObject implements Inf1 {
511     byte b = (byte)1;
512     char c= 'a';
513     short s = (short)2;
514     int i = 3;
515     long l = 4;
516     Object o = new Object();
517     static int sI = 5;
518   }
519 
520   private static class FloatObject extends IntObject implements Inf2 {
521     float f = 1.23f;
522     double d = 1.23;
523     Object p = new Object();
524     static int sI = 6;
525   }
526 
527   public static class Verifier {
528     // Should roots with vreg=-1 be printed?
529     public final static boolean PRINT_ROOTS_WITH_UNKNOWN_VREG = false;
530 
531     public static class Node {
532       public String referrer;
533 
534       public HashSet<String> referrees = new HashSet<>();
535 
Node(String r)536       public Node(String r) {
537         referrer = r;
538       }
539 
isRoot()540       public boolean isRoot() {
541         return referrer.startsWith("root@");
542       }
543     }
544 
545     HashMap<String, Node> nodes = new HashMap<>();
546 
Verifier()547     public Verifier() {
548     }
549 
add(String referrer, String referree)550     public void add(String referrer, String referree) {
551       if (!nodes.containsKey(referrer)) {
552         nodes.put(referrer, new Node(referrer));
553       }
554       if (referree != null) {
555         nodes.get(referrer).referrees.add(referree);
556       }
557     }
558 
process(String[] lines, String additionalEnabledReferrer, boolean filtered)559     public void process(String[] lines, String additionalEnabledReferrer, boolean filtered) {
560       // This method isn't optimal. The loops could be merged. However, it's more readable if
561       // the different parts are separated.
562 
563       ArrayList<String> rootLines = new ArrayList<>();
564       ArrayList<String> nonRootLines = new ArrayList<>();
565 
566       // Check for consecutive chunks of referrers. Also ensure roots come first.
567       {
568         String currentHead = null;
569         boolean rootsDone = false;
570         HashSet<String> completedReferrers = new HashSet<>();
571         for (String l : lines) {
572           String referrer = getReferrer(l);
573 
574           if (isRoot(referrer)) {
575             if (rootsDone) {
576               System.out.println("ERROR: Late root " + l);
577               print(lines);
578               return;
579             }
580             rootLines.add(l);
581             continue;
582           }
583 
584           rootsDone = true;
585 
586           if (currentHead == null) {
587             currentHead = referrer;
588           } else {
589             // Ignore 0@0, as it can happen at any time (as it stands for all other objects).
590             if (!currentHead.equals(referrer) && !referrer.equals("0@0")) {
591               completedReferrers.add(currentHead);
592               currentHead = referrer;
593               if (completedReferrers.contains(referrer)) {
594                 System.out.println("Non-contiguous referrer " + l);
595                 print(lines);
596                 return;
597               }
598             }
599           }
600           nonRootLines.add(l);
601         }
602       }
603 
604       // Sort (root order is not specified) and print the roots.
605       // TODO: What about extra roots? JNI and the interpreter seem to introduce those (though it
606       //       isn't clear why a debuggable-AoT test doesn't have the same, at least for locals).
607       //       For now, swallow duplicates, and resolve once we have the metadata for the roots.
608       {
609         Collections.sort(rootLines);
610         String lastRoot = null;
611         for (String l : rootLines) {
612           if (lastRoot != null && lastRoot.equals(l)) {
613             continue;
614           }
615           lastRoot = l;
616           if (!PRINT_ROOTS_WITH_UNKNOWN_VREG && l.indexOf("vreg=-1") > 0) {
617             continue;
618           }
619           System.out.println(l);
620         }
621       }
622 
623       if (filtered) {
624         // If we aren't tracking dependencies, just sort the lines and print.
625         // TODO: As the verifier is currently using the output lines to track dependencies, we
626         //       cannot verify that output is correct when parts of it are suppressed by filters.
627         //       To correctly track this we need to take node information into account, and
628         //       actually analyze the graph.
629         Collections.sort(nonRootLines);
630         for (String l : nonRootLines) {
631           System.out.println(l);
632         }
633 
634         System.out.println("---");
635         return;
636       }
637 
638       // Iterate through the lines, keeping track of which referrers are visited, to ensure the
639       // order is acceptable.
640       HashSet<String> enabled = new HashSet<>();
641       if (additionalEnabledReferrer != null) {
642         enabled.add(additionalEnabledReferrer);
643       }
644       // Always add "0@0".
645       enabled.add("0@0");
646 
647       for (String l : lines) {
648         String referrer = getReferrer(l);
649         String referree = getReferree(l);
650         if (isRoot(referrer)) {
651           // For a root src, just enable the referree.
652           enabled.add(referree);
653         } else {
654           // Check that the referrer is enabled (may be visited).
655           if (!enabled.contains(referrer)) {
656             System.out.println("Referrer " + referrer + " not enabled: " + l);
657             print(lines);
658             return;
659           }
660           enabled.add(referree);
661         }
662       }
663 
664       // Now just sort the non-root lines and output them
665       Collections.sort(nonRootLines);
666       for (String l : nonRootLines) {
667         System.out.println(l);
668       }
669 
670       System.out.println("---");
671     }
672 
isRoot(String ref)673     public static boolean isRoot(String ref) {
674       return ref.startsWith("root@");
675     }
676 
getReferrer(String line)677     private static String getReferrer(String line) {
678       int i = line.indexOf(" --");
679       if (i <= 0) {
680         throw new IllegalArgumentException(line);
681       }
682       int j = line.indexOf(' ');
683       if (i != j) {
684         throw new IllegalArgumentException(line);
685       }
686       return line.substring(0, i);
687     }
688 
getReferree(String line)689     private static String getReferree(String line) {
690       int i = line.indexOf("--> ");
691       if (i <= 0) {
692         throw new IllegalArgumentException(line);
693       }
694       int j = line.indexOf(' ', i + 4);
695       if (j < 0) {
696         throw new IllegalArgumentException(line);
697       }
698       return line.substring(i + 4, j);
699     }
700 
print(String[] lines)701     private static void print(String[] lines) {
702       for (String l : lines) {
703         System.out.println(l);
704       }
705     }
706   }
707 
setTag(Object o, long tag)708   private static void setTag(Object o, long tag) {
709     Main.setTag(o, tag);
710   }
getTag(Object o)711   private static long getTag(Object o) {
712     return Main.getTag(o);
713   }
714 
setupGcCallback()715   private static native void setupGcCallback();
enableGcTracking(boolean enable)716   private static native void enableGcTracking(boolean enable);
getGcStarts()717   private static native int getGcStarts();
getGcFinishes()718   private static native int getGcFinishes();
forceGarbageCollection()719   private static native void forceGarbageCollection();
720 
checkForExtensionApis()721   private static native void checkForExtensionApis();
getObjectHeapId(long tag)722   private static native int getObjectHeapId(long tag);
getHeapName(int heapId)723   private static native String getHeapName(int heapId);
checkGetObjectHeapIdInCallback(long tag, int heapId)724   private static native void checkGetObjectHeapIdInCallback(long tag, int heapId);
725 
followReferences(int heapFilter, Class<?> klassFilter, Object initialObject, int stopAfter, int followSet, Object jniRef)726   public static native String[] followReferences(int heapFilter, Class<?> klassFilter,
727       Object initialObject, int stopAfter, int followSet, Object jniRef);
followReferencesString(Object initialObject)728   public static native String[] followReferencesString(Object initialObject);
followReferencesPrimitiveArray(Object initialObject)729   public static native String followReferencesPrimitiveArray(Object initialObject);
followReferencesPrimitiveFields(Object initialObject)730   public static native String followReferencesPrimitiveFields(Object initialObject);
731 
iterateThroughHeapExt()732   private static native void iterateThroughHeapExt();
733 }
734