blob: 9868c617f5228d497843b0459c510f49de68e4c0 [file] [log] [blame]
Andreas Gampe3a913092015-01-10 00:26:17 -08001/*
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
17import java.io.File;
18import java.lang.ref.WeakReference;
Mathieu Chartier8a7ef102016-02-22 16:56:54 -080019import java.lang.reflect.Constructor;
Andreas Gampe3a913092015-01-10 00:26:17 -080020import java.lang.reflect.Method;
21import java.lang.reflect.InvocationTargetException;
22
23public class Main {
24 private static final int TEST_LENGTH = 100;
25
26 private static boolean makeArray(int i) {
27 return i % 10 == 0;
28 }
29
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
Mathieu Chartier8a7ef102016-02-22 16:56:54 -080038 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");
Andreas Gampe3a913092015-01-10 00:26:17 -080043 }
Mathieu Chartier8a7ef102016-02-22 16:56:54 -080044 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 }
Andreas Gampe3a913092015-01-10 00:26:17 -080051
Mathieu Chartier8a7ef102016-02-22 16:56:54 -080052 private static void createDumpAndConv() throws RuntimeException {
Andreas Gampe3a913092015-01-10 00:26:17 -080053 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
Mathieu Chartier8a7ef102016-02-22 16:56:54 -080089 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
Andreas Gampe3a913092015-01-10 00:26:17 -0800126 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
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 */
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
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
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}