summaryrefslogtreecommitdiff
path: root/test/912-classes/src/Main.java
diff options
context:
space:
mode:
Diffstat (limited to 'test/912-classes/src/Main.java')
-rw-r--r--test/912-classes/src/Main.java239
1 files changed, 114 insertions, 125 deletions
diff --git a/test/912-classes/src/Main.java b/test/912-classes/src/Main.java
index 6c8858ab65..f3ff2b0668 100644
--- a/test/912-classes/src/Main.java
+++ b/test/912-classes/src/Main.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+package art;
+
import java.lang.ref.Reference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
@@ -21,9 +23,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
-public class Main {
- public static void main(String[] args) throws Exception {
- art.Main.bindAgentJNIForClass(Main.class);
+public class Test912 {
+ public static void run() throws Exception {
+ art.Main.bindAgentJNIForClass(Test912.class);
doTest();
}
@@ -89,18 +91,19 @@ public class Main {
System.out.println();
- testClassEvents();
- }
-
- private static Class<?> proxyClass = null;
-
- private static Class<?> getProxyClass() throws Exception {
- if (proxyClass != null) {
- return proxyClass;
- }
-
- proxyClass = Proxy.getProxyClass(Main.class.getClassLoader(), new Class[] { Runnable.class });
- return proxyClass;
+ // Use a dedicated thread to have a well-defined current thread.
+ Thread classEventsThread = new Thread("ClassEvents") {
+ @Override
+ public void run() {
+ try {
+ testClassEvents();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ classEventsThread.start();
+ classEventsThread.join();
}
private static void testClass(String className) throws Exception {
@@ -166,34 +169,34 @@ public class Main {
}
private static void testClassLoaderClasses() throws Exception {
- ClassLoader boot = ClassLoader.getSystemClassLoader().getParent();
- while (boot.getParent() != null) {
- boot = boot.getParent();
- }
-
System.out.println();
- System.out.println("boot <- src <- src-ex (A,B)");
- ClassLoader cl1 = create(create(boot, DEX1), DEX2);
+ System.out.println("boot <- (B) <- (A,C)");
+ ClassLoader cl1 = DexData.create2(DexData.create1());
Class.forName("B", false, cl1);
Class.forName("A", false, cl1);
printClassLoaderClasses(cl1);
System.out.println();
- System.out.println("boot <- src (B) <- src-ex (A, List)");
- ClassLoader cl2 = create(create(boot, DEX1), DEX2);
+ System.out.println("boot <- (B) <- (A, List)");
+ ClassLoader cl2 = DexData.create2(DexData.create1());
Class.forName("A", false, cl2);
Class.forName("java.util.List", false, cl2);
Class.forName("B", false, cl2.getParent());
printClassLoaderClasses(cl2);
System.out.println();
- System.out.println("boot <- src+src-ex (A,B)");
- ClassLoader cl3 = create(boot, DEX1, DEX2);
+ System.out.println("boot <- 1+2 (A,B)");
+ ClassLoader cl3 = DexData.create12();
Class.forName("B", false, cl3);
Class.forName("A", false, cl3);
printClassLoaderClasses(cl3);
// Check that the boot classloader dumps something non-empty.
+ ClassLoader boot = ClassLoader.getSystemClassLoader().getParent();
+ while (boot.getParent() != null) {
+ boot = boot.getParent();
+ }
+
Class<?>[] bootClasses = getClassLoaderClasses(boot);
if (bootClasses.length == 0) {
throw new RuntimeException("No classes initiated by boot classloader.");
@@ -236,9 +239,10 @@ public class Main {
@Override
public void run() {
try {
- ClassLoader cl6 = create(boot, DEX1, DEX2);
+ ClassLoader cl6 = DexData.create12();
System.out.println("C, true");
Class.forName("C", true, cl6);
+ printClassLoadMessages();
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -249,77 +253,60 @@ public class Main {
dummyThread.start();
dummyThread.join();
- ensureJitCompiled(Main.class, "testClassEvents");
-
- enableClassLoadPreparePrintEvents(true);
+ enableClassLoadPreparePrintEvents(true, Thread.currentThread());
- ClassLoader cl1 = create(boot, DEX1, DEX2);
+ ClassLoader cl1 = DexData.create12();
System.out.println("B, false");
Class.forName("B", false, cl1);
+ printClassLoadMessages();
- ClassLoader cl2 = create(boot, DEX1, DEX2);
+ ClassLoader cl2 = DexData.create12();
System.out.println("B, true");
Class.forName("B", true, cl2);
+ printClassLoadMessages();
- ClassLoader cl3 = create(boot, DEX1, DEX2);
+ ClassLoader cl3 = DexData.create12();
System.out.println("C, false");
Class.forName("C", false, cl3);
+ printClassLoadMessages();
System.out.println("A, false");
Class.forName("A", false, cl3);
+ printClassLoadMessages();
- ClassLoader cl4 = create(boot, DEX1, DEX2);
+ ClassLoader cl4 = DexData.create12();
System.out.println("C, true");
Class.forName("C", true, cl4);
+ printClassLoadMessages();
System.out.println("A, true");
Class.forName("A", true, cl4);
+ printClassLoadMessages();
- ClassLoader cl5 = create(boot, DEX1, DEX2);
+ ClassLoader cl5 = DexData.create12();
System.out.println("A, true");
Class.forName("A", true, cl5);
+ printClassLoadMessages();
System.out.println("C, true");
Class.forName("C", true, cl5);
+ printClassLoadMessages();
+
+ enableClassLoadPreparePrintEvents(false, null);
Thread t = new Thread(r, "TestRunner");
+ enableClassLoadPreparePrintEvents(true, t);
t.start();
t.join();
+ enableClassLoadPreparePrintEvents(false, null);
- // Check creation of arrays and proxies.
- Proxy.getProxyClass(Main.class.getClassLoader(), new Class[] { Comparable.class });
- Class.forName("[LMain;");
-
- enableClassLoadPreparePrintEvents(false);
-
- // Note: the JIT part of this test is about the JIT pulling in a class not yet touched by
- // anything else in the system. This could be the verifier or the interpreter. We
- // block the interpreter by calling ensureJitCompiled. The verifier, however, must
- // run in configurations where dex2oat didn't verify the class itself. So explicitly
- // check whether the class has been already loaded, and skip then.
- // TODO: Add multiple configurations to the run script once that becomes easier to do.
- if (hasJit() && !isLoadedClass("Main$ClassD")) {
- testClassEventsJit();
- }
-
- testClassLoadPrepareEquality();
- }
-
- private static void testClassEventsJit() throws Exception {
- enableClassLoadSeenEvents(true);
+ enableClassLoadPreparePrintEvents(true, Thread.currentThread());
- testClassEventsJitImpl();
-
- enableClassLoadSeenEvents(false);
-
- if (!hadLoadEvent()) {
- throw new RuntimeException("Did not get expected load event.");
- }
- }
+ // Check creation of arrays and proxies.
+ Proxy.getProxyClass(Main.class.getClassLoader(), new Class[] { Comparable.class, I0.class });
+ Class.forName("[Lart.Test912;");
+ printClassLoadMessages();
- private static void testClassEventsJitImpl() throws Exception {
- ensureJitCompiled(Main.class, "testClassEventsJitImpl");
+ enableClassLoadPreparePrintEvents(false, null);
- if (ClassD.x != 1) {
- throw new RuntimeException("Unexpected value");
- }
+ testClassLoadPrepareEquality();
}
private static void testClassLoadPrepareEquality() throws Exception {
@@ -327,7 +314,7 @@ public class Main {
enableClassLoadPrepareEqualityEvents(true);
- Class.forName("Main$ClassE");
+ Class.forName("art.Test912$ClassE");
enableClassLoadPrepareEqualityEvents(false);
}
@@ -338,39 +325,17 @@ public class Main {
break;
}
- ClassLoader saved = cl;
- for (;;) {
- if (cl == null || !cl.getClass().getName().startsWith("dalvik.system")) {
- break;
- }
- String s = cl.toString();
- int index1 = s.indexOf("zip file");
- int index2 = s.indexOf(']', index1);
- if (index2 < 0) {
- throw new RuntimeException("Unexpected classloader " + s);
- }
- String zip_file = s.substring(index1, index2);
- int index3 = zip_file.indexOf('"');
- int index4 = zip_file.indexOf('"', index3 + 1);
- if (index4 < 0) {
- throw new RuntimeException("Unexpected classloader " + s);
- }
- String paths = zip_file.substring(index3 + 1, index4);
- String pathArray[] = paths.split(":");
- for (String path : pathArray) {
- int index5 = path.lastIndexOf('/');
- System.out.print(path.substring(index5 + 1));
- System.out.print('+');
- }
- System.out.print(" -> ");
- cl = cl.getParent();
- }
- System.out.println();
- Class<?> classes[] = getClassLoaderClasses(saved);
+ Class<?> classes[] = getClassLoaderClasses(cl);
Arrays.sort(classes, new ClassNameComparator());
System.out.println(Arrays.toString(classes));
- cl = saved.getParent();
+ cl = cl.getParent();
+ }
+ }
+
+ private static void printClassLoadMessages() {
+ for (String s : getClassLoadMessages()) {
+ System.out.println(s);
}
}
@@ -394,14 +359,8 @@ public class Main {
private static native int[] getClassVersion(Class<?> c);
- private static native void enableClassLoadPreparePrintEvents(boolean b);
-
- private static native void ensureJitCompiled(Class<?> c, String name);
-
- private static native boolean hasJit();
- private static native boolean isLoadedClass(String name);
- private static native void enableClassLoadSeenEvents(boolean b);
- private static native boolean hadLoadEvent();
+ private static native void enableClassLoadPreparePrintEvents(boolean b, Thread filter);
+ private static native String[] getClassLoadMessages();
private static native void setEqualityEventStorageClass(Class<?> c);
private static native void enableClassLoadPrepareEqualityEvents(boolean b);
@@ -428,10 +387,6 @@ public class Main {
public abstract static class ClassC implements InfA, InfC {
}
- public static class ClassD {
- static int x = 1;
- }
-
public static class ClassE {
public void foo() {
}
@@ -444,22 +399,56 @@ public class Main {
public static Reference<Object> WEAK = null;
}
- private static final String DEX1 = System.getenv("DEX_LOCATION") + "/912-classes.jar";
- private static final String DEX2 = System.getenv("DEX_LOCATION") + "/912-classes-ex.jar";
-
- private static ClassLoader create(ClassLoader parent, String... elements) throws Exception {
- // Note: We use a PathClassLoader, as we do not care about code performance. We only load
- // the classes, and they're empty.
- Class<?> pathClassLoaderClass = Class.forName("dalvik.system.PathClassLoader");
- Constructor<?> pathClassLoaderInit = pathClassLoaderClass.getConstructor(String.class,
- ClassLoader.class);
- String path = String.join(":", elements);
- return (ClassLoader) pathClassLoaderInit.newInstance(path, parent);
- }
-
private static class ClassNameComparator implements Comparator<Class<?>> {
public int compare(Class<?> c1, Class<?> c2) {
return c1.getName().compareTo(c2.getName());
}
}
+
+ // See run-test 910 for an explanation.
+
+ private static Class<?> proxyClass = null;
+
+ private static Class<?> getProxyClass() throws Exception {
+ if (proxyClass != null) {
+ return proxyClass;
+ }
+
+ for (int i = 1; i <= 21; i++) {
+ proxyClass = createProxyClass(i);
+ String name = proxyClass.getName();
+ if (name.equals("$Proxy20")) {
+ return proxyClass;
+ }
+ }
+ return proxyClass;
+ }
+
+ private static Class<?> createProxyClass(int i) throws Exception {
+ int count = Integer.bitCount(i);
+ Class<?>[] input = new Class<?>[count + 1];
+ input[0] = Runnable.class;
+ int inputIndex = 1;
+ int bitIndex = 0;
+ while (i != 0) {
+ if ((i & 1) != 0) {
+ input[inputIndex++] = Class.forName("art.Test912$I" + bitIndex);
+ }
+ i >>>= 1;
+ bitIndex++;
+ }
+ return Proxy.getProxyClass(Test912.class.getClassLoader(), input);
+ }
+
+ // Need this for the proxy naming.
+ public static interface I0 {
+ }
+ public static interface I1 {
+ }
+ public static interface I2 {
+ }
+ public static interface I3 {
+ }
+ public static interface I4 {
+ }
}