• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 java.io.File;
18 import java.lang.ref.WeakReference;
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.InvocationTargetException;
22 
23 public class Main {
24     private static final int TEST_LENGTH = 100;
25 
makeArray(int i)26     private static boolean makeArray(int i) {
27         return i % 10 == 0;
28     }
29 
fillArray(Object global[], Object local[], int i)30     private static void fillArray(Object global[], Object local[], int i) {
31         // Very stupid linking.
32         local[0] = global;
33         for (int j = 1; j < local.length; j++) {
34             local[j] = global[j];
35         }
36     }
37 
allocInDifferentLoader()38     private static Object allocInDifferentLoader() throws Exception {
39         final String DEX_FILE = System.getenv("DEX_LOCATION") + "/130-hprof-ex.jar";
40         Class pathClassLoader = Class.forName("dalvik.system.PathClassLoader");
41         if (pathClassLoader == null) {
42             throw new AssertionError("Couldn't find path class loader class");
43         }
44         Constructor constructor =
45             pathClassLoader.getDeclaredConstructor(String.class, ClassLoader.class);
46         ClassLoader loader = (ClassLoader)constructor.newInstance(
47                 DEX_FILE, ClassLoader.getSystemClassLoader());
48         Class allocator = loader.loadClass("Allocator");
49         return allocator.getDeclaredMethod("allocObject", null).invoke(null);
50     }
51 
createDumpAndConv()52     private static void createDumpAndConv() throws RuntimeException {
53         File dumpFile = null;
54         File convFile = null;
55 
56         try {
57             // Now dump the heap.
58             dumpFile = createDump();
59 
60             // Run hprof-conv on it.
61             convFile = getConvFile();
62 
63             File hprof_conv = getHprofConf();
64             try {
65                 ProcessBuilder pb = new ProcessBuilder(
66                         hprof_conv.getAbsoluteFile().toString(),
67                         dumpFile.getAbsoluteFile().toString(),
68                         convFile.getAbsoluteFile().toString());
69                 pb.redirectErrorStream(true);
70                 Process process = pb.start();
71                 int ret = process.waitFor();
72                 if (ret != 0) {
73                     throw new RuntimeException("Exited abnormally with " + ret);
74                 }
75             } catch (Exception exc) {
76                 throw new RuntimeException(exc);
77             }
78         } finally {
79             // Delete the files.
80             if (dumpFile != null) {
81                 dumpFile.delete();
82             }
83             if (convFile != null) {
84                 convFile.delete();
85             }
86         }
87     }
88 
main(String[] args)89     public static void main(String[] args) throws Exception {
90         // Create some data.
91         Object data[] = new Object[TEST_LENGTH];
92         for (int i = 0; i < data.length; i++) {
93             if (makeArray(i)) {
94                 data[i] = new Object[TEST_LENGTH];
95             } else {
96                 data[i] = String.valueOf(i);
97             }
98         }
99         for (int i = 0; i < data.length; i++) {
100             if (makeArray(i)) {
101                 Object data2[] = (Object[]) data[i];
102                 fillArray(data, data2, i);
103             }
104         }
105         System.out.println("Generated data.");
106 
107         createDumpAndConv();
108         Class klass = Class.forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal");
109         if (klass == null) {
110             throw new AssertionError("Couldn't find path class loader class");
111         }
112         Method enableMethod = klass.getDeclaredMethod("enableRecentAllocations",
113                 Boolean.TYPE);
114         if (enableMethod == null) {
115             throw new AssertionError("Couldn't find path class loader class");
116         }
117         enableMethod.invoke(null, true);
118         Object o = allocInDifferentLoader();
119         // Run GC to cause class unloading.
120         Runtime.getRuntime().gc();
121         createDumpAndConv();
122         // TODO: Somehow check contents of hprof file.
123         enableMethod.invoke(null, false);
124     }
125 
getHprofConf()126     private static File getHprofConf() {
127         // Use the java.library.path. It points to the lib directory.
128         File libDir = new File(System.getProperty("java.library.path"));
129         return new File(new File(libDir.getParentFile(), "bin"), "hprof-conv");
130     }
131 
createDump()132     private static File createDump() {
133         java.lang.reflect.Method dumpHprofDataMethod = getDumpHprofDataMethod();
134         if (dumpHprofDataMethod != null) {
135             File f = getDumpFile();
136             try {
137                 dumpHprofDataMethod.invoke(null, f.getAbsoluteFile().toString());
138                 return f;
139             } catch (Exception exc) {
140                 exc.printStackTrace(System.out);
141             }
142         } else {
143             System.out.println("Could not find dump method!");
144         }
145         return null;
146     }
147 
148     /**
149      * Finds VMDebug.dumpHprofData() through reflection.  In the reference
150      * implementation this will not be available.
151      *
152      * @return the reflection object, or null if the method can't be found
153      */
getDumpHprofDataMethod()154     private static Method getDumpHprofDataMethod() {
155         ClassLoader myLoader = Main.class.getClassLoader();
156         Class vmdClass;
157         try {
158             vmdClass = myLoader.loadClass("dalvik.system.VMDebug");
159         } catch (ClassNotFoundException cnfe) {
160             return null;
161         }
162 
163         Method meth;
164         try {
165             meth = vmdClass.getMethod("dumpHprofData",
166                     new Class[] { String.class });
167         } catch (NoSuchMethodException nsme) {
168             System.err.println("Found VMDebug but not dumpHprofData method");
169             return null;
170         }
171 
172         return meth;
173     }
174 
getDumpFile()175     private static File getDumpFile() {
176         try {
177             return File.createTempFile("test-130-hprof", "dump");
178         } catch (Exception exc) {
179             return null;
180         }
181     }
182 
getConvFile()183     private static File getConvFile() {
184         try {
185             return File.createTempFile("test-130-hprof", "conv");
186         } catch (Exception exc) {
187             return null;
188         }
189     }
190 }
191