1 /* 2 * Copyright (C) 2015 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 import dalvik.system.VMDebug; 18 import java.io.IOException; 19 import java.lang.ref.PhantomReference; 20 import java.lang.ref.ReferenceQueue; 21 import java.lang.ref.SoftReference; 22 import java.lang.ref.WeakReference; 23 import org.apache.harmony.dalvik.ddmc.DdmVmInternal; 24 25 /** 26 * Program used to create a heap dump for test purposes. 27 */ 28 public class Main { 29 // Keep a reference to the DumpedStuff instance so that it is not garbage 30 // collected before we take the heap dump. 31 public static DumpedStuff stuff; 32 33 public static class ObjectTree { 34 public ObjectTree left; 35 public ObjectTree right; 36 ObjectTree(ObjectTree left, ObjectTree right)37 public ObjectTree(ObjectTree left, ObjectTree right) { 38 this.left = left; 39 this.right = right; 40 } 41 } 42 43 public static class AddedObject { 44 } 45 46 public static class RemovedObject { 47 } 48 49 public static class UnchangedObject { 50 } 51 52 public static class ModifiedObject { 53 public int value; 54 public String modifiedRefField; 55 public String unmodifiedRefField; 56 } 57 58 public static class StackSmasher { 59 public StackSmasher child; 60 } 61 62 // We will take a heap dump that includes a single instance of this 63 // DumpedStuff class. Objects stored as fields in this class can be easily 64 // found in the hprof dump by searching for the instance of the DumpedStuff 65 // class and reading the desired field. 66 public static class DumpedStuff { 67 public String basicString = "hello, world"; 68 public String nonAscii = "Sigma (Ʃ) is not ASCII"; 69 public String embeddedZero = "embedded\0..."; // Non-ASCII for string compression purposes. 70 public char[] charArray = "char thing".toCharArray(); 71 public String nullString = null; 72 public Object anObject = new Object(); 73 public ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>(); 74 public PhantomReference aPhantomReference = new PhantomReference(anObject, referenceQueue); 75 public WeakReference aWeakReference = new WeakReference(anObject, referenceQueue); 76 public WeakReference aNullReferentReference = new WeakReference(null, referenceQueue); 77 public SoftReference aSoftReference = new SoftReference(new Object()); 78 public byte[] bigArray; 79 public ObjectTree[] gcPathArray = new ObjectTree[]{null, null, 80 new ObjectTree( 81 new ObjectTree(null, new ObjectTree(null, null)), 82 new ObjectTree(null, null)), 83 null}; 84 public Object[] basicStringRef; 85 public AddedObject addedObject; 86 public UnchangedObject unchangedObject = new UnchangedObject(); 87 public RemovedObject removedObject; 88 public ModifiedObject modifiedObject; 89 public StackSmasher stackSmasher; 90 public StackSmasher stackSmasherAdded; 91 public static String modifiedStaticField; 92 public int[] modifiedArray; 93 DumpedStuff(boolean baseline)94 DumpedStuff(boolean baseline) { 95 int N = baseline ? 400000 : 1000000; 96 bigArray = new byte[N]; 97 for (int i = 0; i < N; i++) { 98 bigArray[i] = (byte)((i*i) & 0xFF); 99 } 100 101 addedObject = baseline ? null : new AddedObject(); 102 removedObject = baseline ? new RemovedObject() : null; 103 modifiedObject = new ModifiedObject(); 104 modifiedObject.value = baseline ? 5 : 8; 105 modifiedObject.modifiedRefField = baseline ? "A1" : "A2"; 106 modifiedObject.unmodifiedRefField = "B"; 107 modifiedStaticField = baseline ? "C1" : "C2"; 108 modifiedArray = baseline ? new int[]{0,1,2,3} : new int[]{3,1,2,0}; 109 110 // Deep matching dominator trees shouldn't smash the stack when we try 111 // to diff them. Make some deep dominator trees to help test it. 112 for (int i = 0; i < 10000; i++) { 113 StackSmasher smasher = new StackSmasher(); 114 smasher.child = stackSmasher; 115 stackSmasher = smasher; 116 117 if (!baseline) { 118 smasher = new StackSmasher(); 119 smasher.child = stackSmasherAdded; 120 stackSmasherAdded = smasher; 121 } 122 } 123 124 gcPathArray[2].right.left = gcPathArray[2].left.right; 125 } 126 } 127 main(String[] args)128 public static void main(String[] args) throws IOException { 129 if (args.length < 1) { 130 System.err.println("no output file specified"); 131 return; 132 } 133 String file = args[0]; 134 135 // If a --base argument is provided, it means we should generate a 136 // baseline hprof file suitable for using in testing diff. 137 boolean baseline = args.length > 1 && args[1].equals("--base"); 138 139 // Enable allocation tracking so we get stack traces in the heap dump. 140 DdmVmInternal.enableRecentAllocations(true); 141 142 // Allocate the instance of DumpedStuff. 143 stuff = new DumpedStuff(baseline); 144 145 // Create a bunch of unreachable objects pointing to basicString for the 146 // reverseReferencesAreNotUnreachable test 147 for (int i = 0; i < 100; i++) { 148 stuff.basicStringRef = new Object[]{stuff.basicString}; 149 } 150 151 // Take a heap dump that will include that instance of DumpedStuff. 152 System.err.println("Dumping hprof data to " + file); 153 VMDebug.dumpHprofData(file); 154 } 155 } 156