/*
* Copyright ( C ) 2010 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.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
/**
* Class loader test .
*/
public class Main {
/**
* Thrown when an unexpected Exception is caught internally .
*/
static class TestFailed extends Exception {
public TestFailed(Throwable cause) {
super (cause);
}
}
/**
* A class loader which loads classes from the dex file
* " test . jar " . However , it will return null when asked to load the
* class InaccessibleSuper .
*
* When testing code calls BrokenDexLoader ' s findBrokenClass ( ) ,
* a BrokenDexLoader will be the defining loader for the class
* Inaccessible . The VM will call the defining loader for
* " InaccessibleSuper " , which will return null , which the VM
* should be able to deal with gracefully .
*
* Note that this depends heavily on the Dalvik test harness .
*/
static class BrokenDexLoader extends ClassLoader {
/** We return null when asked to load InaccessibleSuper. */
private static class InaccessibleSuper {}
private static class Inaccessible extends InaccessibleSuper {}
private static final String SUPERCLASS_NAME =
"Main$BrokenDexLoader$InaccessibleSuper" ;
private static final String CLASS_NAME =
"Main$BrokenDexLoader$Inaccessible" ;
private static final String DEX_FILE = System.getenv("DEX_LOCATION" ) + "/087-gc-after-link.jar" ;
public BrokenDexLoader(ClassLoader parent) {
super (parent);
}
/**
* Finds the class with the specified binary name , from DEX_FILE .
*
* If we don ' t find a match , we throw an exception .
*/
private Class <?> findDexClass(String name)
throws TestFailed, InvocationTargetException
{
Object dexFile = null ;
Class <?> dexClass = null ;
try {
try {
/*
* Find the DexFile class , and construct a DexFile object
* through reflection , then call loadClass on it .
*/
dexClass = ClassLoader.getSystemClassLoader().
loadClass("dalvik.system.DexFile" );
Constructor<?> ctor = dexClass.getConstructor(String.class );
dexFile = ctor.newInstance(DEX_FILE);
Method meth = dexClass.getMethod("loadClass" , String.class , ClassLoader.class );
/*
* Invoking loadClass on CLASS_NAME is expected to
* throw an InvocationTargetException . Anything else
* is an error we can ' t recover from .
*/
meth.invoke(dexFile, name, this );
System.out.println("Unreachable" );
} finally {
if (dexFile != null ) {
/* close the DexFile to make CloseGuard happy */
Method meth = dexClass.getMethod("close" );
meth.invoke(dexFile);
}
}
} catch (NoSuchMethodException nsme) {
throw new TestFailed(nsme);
} catch (InstantiationException ie) {
throw new TestFailed(ie);
} catch (IllegalAccessException iae) {
throw new TestFailed(iae);
} catch (ClassNotFoundException cnfe) {
throw new TestFailed(cnfe);
}
return null ;
}
/**
* Load a class .
*
* Return null if the class ' s name is SUPERCLASS_NAME ;
* otherwise invoke the super ' s loadClass method .
*/
public Class <?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
if (SUPERCLASS_NAME.equals(name)) {
return null ;
}
return super .loadClass(name, resolve);
}
/**
* Attempt to find the class with the superclass we refuse to
* load . This is expected to throw an
* InvocationTargetException , with a NullPointerException as
* its cause .
*/
public void findBrokenClass()
throws TestFailed, InvocationTargetException
{
findDexClass(CLASS_NAME);
}
}
/**
* Main entry point .
*/
public static void main(String[] args)
throws TestFailed, ClassNotFoundException {
/*
* Run test .
*/
testFailLoadAndGc();
}
/**
* See if we can GC after a failed load .
*/
static void testFailLoadAndGc() throws TestFailed {
processFailLoadAndGc();
Runtime.getRuntime().gc();
System.out.println("GC complete." );
}
private static void processFailLoadAndGc() throws TestFailed {
try {
BrokenDexLoader loader;
loader = new BrokenDexLoader(ClassLoader.getSystemClassLoader());
loader.findBrokenClass();
System.out.println("ERROR: Inaccessible was accessible" );
} catch (InvocationTargetException ite) {
Throwable cause = ite.getCause();
if (cause instanceof NullPointerException) {
System.out.println("Got expected ITE/NPE" );
} else {
System.out.println("Got unexpected ITE" );
ite.printStackTrace(System.out);
}
}
}
}
Messung V0.5 in Prozent C=91 H=92 G=91
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-29)
¤
*© Formatika GbR, Deutschland