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
17import java.io.File;
18import java.lang.ref.WeakReference;
19import java.lang.reflect.Method;
20import java.lang.reflect.InvocationTargetException;
21
22public class Main {
23    private static final int TEST_LENGTH = 100;
24
25    private static boolean makeArray(int i) {
26        return i % 10 == 0;
27    }
28
29    private static void fillArray(Object global[], Object local[], int i) {
30        // Very stupid linking.
31        local[0] = global;
32        for (int j = 1; j < local.length; j++) {
33            local[j] = global[j];
34        }
35    }
36
37    public static void main(String[] args) {
38        // Create some data.
39        Object data[] = new Object[TEST_LENGTH];
40        for (int i = 0; i < data.length; i++) {
41            if (makeArray(i)) {
42                data[i] = new Object[TEST_LENGTH];
43            } else {
44                data[i] = String.valueOf(i);
45            }
46        }
47        for (int i = 0; i < data.length; i++) {
48            if (makeArray(i)) {
49                Object data2[] = (Object[]) data[i];
50                fillArray(data, data2, i);
51            }
52        }
53        System.out.println("Generated data.");
54
55        File dumpFile = null;
56        File convFile = null;
57
58        try {
59            // Now dump the heap.
60            dumpFile = createDump();
61
62            // Run hprof-conv on it.
63            convFile = getConvFile();
64
65            File hprof_conv = getHprofConf();
66            try {
67                ProcessBuilder pb = new ProcessBuilder(
68                        hprof_conv.getAbsoluteFile().toString(),
69                        dumpFile.getAbsoluteFile().toString(),
70                        convFile.getAbsoluteFile().toString());
71                pb.redirectErrorStream(true);
72                Process process = pb.start();
73                int ret = process.waitFor();
74                if (ret != 0) {
75                    throw new RuntimeException("Exited abnormally with " + ret);
76                }
77            } catch (Exception exc) {
78                throw new RuntimeException(exc);
79            }
80        } finally {
81            // Delete the files.
82            if (dumpFile != null) {
83                dumpFile.delete();
84            }
85            if (convFile != null) {
86                convFile.delete();
87            }
88        }
89    }
90
91    private static File getHprofConf() {
92        // Use the java.library.path. It points to the lib directory.
93        File libDir = new File(System.getProperty("java.library.path"));
94        return new File(new File(libDir.getParentFile(), "bin"), "hprof-conv");
95    }
96
97    private static File createDump() {
98        java.lang.reflect.Method dumpHprofDataMethod = getDumpHprofDataMethod();
99        if (dumpHprofDataMethod != null) {
100            File f = getDumpFile();
101            try {
102                dumpHprofDataMethod.invoke(null, f.getAbsoluteFile().toString());
103                return f;
104            } catch (Exception exc) {
105                exc.printStackTrace(System.out);
106            }
107        } else {
108            System.out.println("Could not find dump method!");
109        }
110        return null;
111    }
112
113    /**
114     * Finds VMDebug.dumpHprofData() through reflection.  In the reference
115     * implementation this will not be available.
116     *
117     * @return the reflection object, or null if the method can't be found
118     */
119    private static Method getDumpHprofDataMethod() {
120        ClassLoader myLoader = Main.class.getClassLoader();
121        Class vmdClass;
122        try {
123            vmdClass = myLoader.loadClass("dalvik.system.VMDebug");
124        } catch (ClassNotFoundException cnfe) {
125            return null;
126        }
127
128        Method meth;
129        try {
130            meth = vmdClass.getMethod("dumpHprofData",
131                    new Class[] { String.class });
132        } catch (NoSuchMethodException nsme) {
133            System.err.println("Found VMDebug but not dumpHprofData method");
134            return null;
135        }
136
137        return meth;
138    }
139
140    private static File getDumpFile() {
141        try {
142            return File.createTempFile("test-130-hprof", "dump");
143        } catch (Exception exc) {
144            return null;
145        }
146    }
147
148    private static File getConvFile() {
149        try {
150            return File.createTempFile("test-130-hprof", "conv");
151        } catch (Exception exc) {
152            return null;
153        }
154    }
155}
156