/*
* Copyright ( C ) 2009 The Android Open Source Project
*
* Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Main {
private static final int TEST_LENGTH = 100 ;
private static boolean makeArray(int i) {
return i % 10 == 0 ;
}
private static void fillArray(Object global[], Object local[], int i) {
// Very stupid linking.
local[0 ] = global;
for (int j = 1 ; j < local.length; j++) {
local[j] = global[j];
}
}
private static Object allocInDifferentLoader() throws Exception {
final String DEX_FILE = System.getenv("DEX_LOCATION" ) + "/130-hprof-ex.jar" ;
Class <?> pathClassLoader = Class .forName("dalvik.system.PathClassLoader" );
if (pathClassLoader == null ) {
throw new AssertionError("Couldn't find path class loader class" );
}
Constructor<?> constructor =
pathClassLoader.getDeclaredConstructor(String.class , ClassLoader.class );
ClassLoader loader = (ClassLoader)constructor.newInstance(
DEX_FILE, ClassLoader.getSystemClassLoader());
Class <?> allocator = loader.loadClass("Allocator" );
return allocator.getDeclaredMethod("allocObject" , null ).invoke(null );
}
private static void createDumpAndConv() throws RuntimeException {
File dumpFile = null ;
File convFile = null ;
try {
// Now dump the heap.
dumpFile = createDump();
// Run hprof-conv on it.
convFile = getConvFile();
File hprof_conv = getHprofConf();
try {
ProcessBuilder pb = new ProcessBuilder(
hprof_conv.getAbsoluteFile().toString(),
dumpFile.getAbsoluteFile().toString(),
convFile.getAbsoluteFile().toString());
pb.redirectErrorStream(true );
Process process = pb.start();
int ret = process.waitFor();
if (ret != 0 ) {
throw new RuntimeException("Exited abnormally with " + ret);
}
} catch (Exception exc) {
throw new RuntimeException(exc);
}
} finally {
// Delete the files.
if (dumpFile != null ) {
dumpFile.delete ();
}
if (convFile != null ) {
convFile.delete ();
}
}
}
public static void main(String[] args) throws Exception {
testBasicDump();
testAllocationTrackingAndClassUnloading();
testGcAndDump();
}
private static void testBasicDump() throws Exception {
// Create some data.
Object data[] = new Object[TEST_LENGTH];
for (int i = 0 ; i < data.length; i++) {
if (makeArray(i)) {
data[i] = new Object[TEST_LENGTH];
} else {
data[i] = String.valueOf(i);
}
}
for (int i = 0 ; i < data.length; i++) {
if (makeArray(i)) {
Object data2[] = (Object[]) data[i];
fillArray(data, data2, i);
}
}
System.out.println("Generated data." );
createDumpAndConv();
}
private static void testAllocationTrackingAndClassUnloading() throws Exception {
Class <?> klass = Class .forName("org.apache.harmony.dalvik.ddmc.DdmVmInternal" );
if (klass == null ) {
throw new AssertionError("Couldn't find path class loader class" );
}
Method enableMethod = klass.getDeclaredMethod("setRecentAllocationsTrackingEnabled" ,
boolean .class );
if (enableMethod == null ) {
throw new AssertionError("Couldn't find setRecentAllocationsTrackingEnabled method" );
}
enableMethod.invoke(null , true );
Object o = allocInDifferentLoader();
// Run GC to cause class unloading.
Runtime.getRuntime().gc();
createDumpAndConv();
// TODO: Somehow check contents of hprof file.
enableMethod.invoke(null , false );
}
private static void testGcAndDump() throws Exception {
Allocator allocator = new Allocator();
Dumper dumper = new Dumper(allocator);
allocator.start();
dumper.start();
try {
allocator.join();
dumper.join();
} catch (InterruptedException e) {
System.out.println("join interrupted" );
}
}
private static class Allocator extends Thread {
private static int ARRAY_SIZE = 1024 ;
public volatile boolean running = true ;
public void run() {
Object[] array = new Object[ARRAY_SIZE];
int i = 0 ;
while (running) {
array[i] = new byte [1024 ];
if (i % ARRAY_SIZE == 0 ) {
Main.sleep(100 L);
}
i = (i + 1 ) % ARRAY_SIZE;
}
}
}
private static class Dumper extends Thread {
Dumper(Allocator allocator) {
this .allocator = allocator;
}
Allocator allocator;
public void run() {
for (int i = 0 ; i < 5 ; ++i) {
Main.sleep(1000 L);
createDumpAndConv();
}
allocator.running = false ;
}
}
public static void sleep(long ms) {
try {
Thread .sleep(ms);
} catch (InterruptedException e) {
System.out.println("sleep interrupted" );
}
}
private static File getHprofConf() {
// Use the java.library.path. It points to the lib directory.
File libDir = new File(System.getProperty("java.library.path" ).split(":" )[0 ]);
return new File(new File(libDir.getParentFile(), "bin" ), "hprof-conv" );
}
private static File createDump() {
java.lang.reflect.Method dumpHprofDataMethod = getDumpHprofDataMethod();
if (dumpHprofDataMethod != null ) {
File f = getDumpFile();
try {
dumpHprofDataMethod.invoke(null , f.getAbsoluteFile().toString());
return f;
} catch (Exception exc) {
exc.printStackTrace(System.out);
}
} else {
System.out.println("Could not find dump method!" );
}
return null ;
}
/**
* Finds VMDebug . dumpHprofData ( ) through reflection . In the reference
* implementation this will not be available .
*
* @ return the reflection object , or null if the method can ' t be found
*/
private static Method getDumpHprofDataMethod() {
ClassLoader myLoader = Main.class .getClassLoader();
Class <?> vmdClass;
try {
vmdClass = myLoader.loadClass("dalvik.system.VMDebug" );
} catch (ClassNotFoundException cnfe) {
return null ;
}
Method meth;
try {
meth = vmdClass.getMethod("dumpHprofData" , String.class );
} catch (NoSuchMethodException nsme) {
System.out.println("Found VMDebug but not dumpHprofData method" );
return null ;
}
return meth;
}
private static File getDumpFile() {
try {
return File.createTempFile("test-130-hprof" , "dump" );
} catch (Exception exc) {
return null ;
}
}
private static File getConvFile() {
try {
return File.createTempFile("test-130-hprof" , "conv" );
} catch (Exception exc) {
return null ;
}
}
}
Messung V0.5 in Prozent C=87 H=97 G=91
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-29)
¤
*© Formatika GbR, Deutschland