summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/004-NativeAllocations/src/Main.java12
-rw-r--r--test/008-exceptions/expected.txt18
-rw-r--r--test/008-exceptions/multidex.jpp27
-rw-r--r--test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java24
-rw-r--r--test/008-exceptions/src/Main.java85
-rw-r--r--test/008-exceptions/src/MultiDexBadInit.java25
-rw-r--r--test/008-exceptions/src/MultiDexBadInitWrapper1.java24
-rw-r--r--test/082-inline-execute/src/Main.java18
-rw-r--r--test/142-classloader2/expected.txt4
-rw-r--r--test/142-classloader2/src/Main.java15
-rw-r--r--test/154-gc-loop/expected.txt2
-rw-r--r--test/154-gc-loop/heap_interface.cc28
-rw-r--r--test/154-gc-loop/info.txt1
-rw-r--r--test/154-gc-loop/src/Main.java45
-rw-r--r--test/466-get-live-vreg/get_live_vreg_jni.cc2
-rw-r--r--test/482-checker-loop-back-edge-use/src/Main.java9
-rw-r--r--test/552-checker-sharpening/src/Main.java56
-rw-r--r--test/616-cha-abstract/expected.txt1
-rw-r--r--test/616-cha-abstract/info.txt1
-rw-r--r--test/616-cha-abstract/run18
-rw-r--r--test/616-cha-abstract/src/Main.java159
-rw-r--r--test/623-checker-loop-regressions/src/Main.java121
-rw-r--r--test/626-checker-arm64-scratch-register/src/Main.java4
-rw-r--r--test/626-const-class-linking/clear_dex_cache_types.cc3
-rw-r--r--test/635-checker-arm64-volatile-load-cc/expected.txt1
-rw-r--r--test/635-checker-arm64-volatile-load-cc/info.txt3
-rw-r--r--test/635-checker-arm64-volatile-load-cc/src/Main.java284
-rw-r--r--test/636-wrong-static-access/expected.txt1
-rw-r--r--test/636-wrong-static-access/info.txt2
-rwxr-xr-xtest/636-wrong-static-access/run20
-rw-r--r--test/636-wrong-static-access/src-ex/Foo.java38
-rw-r--r--test/636-wrong-static-access/src/Holder.java19
-rw-r--r--test/636-wrong-static-access/src/Main.java39
-rw-r--r--test/636-wrong-static-access/src2/Holder.java19
-rw-r--r--test/706-checker-scheduler/expected.txt0
-rw-r--r--test/706-checker-scheduler/info.txt1
-rw-r--r--test/706-checker-scheduler/src/Main.java82
-rwxr-xr-xtest/900-hello-plugin/run4
-rwxr-xr-xtest/901-hello-ti-agent/run4
-rwxr-xr-xtest/902-hello-transformation/run4
-rwxr-xr-xtest/903-hello-tagging/run4
-rwxr-xr-xtest/904-object-allocation/run4
-rwxr-xr-xtest/905-object-free/run4
-rwxr-xr-xtest/906-iterate-heap/run4
-rwxr-xr-xtest/907-get-loaded-classes/run4
-rw-r--r--test/908-gc-start-finish/gc_callbacks.cc25
-rwxr-xr-xtest/908-gc-start-finish/run4
-rwxr-xr-xtest/909-attach-agent/run16
-rw-r--r--test/909-attach-agent/src/Main.java4
-rwxr-xr-xtest/910-methods/run4
-rwxr-xr-xtest/911-get-stack-trace/run4
-rw-r--r--test/911-get-stack-trace/src/PrintThread.java3
-rw-r--r--test/912-classes/expected.txt2
-rwxr-xr-xtest/912-classes/run4
-rwxr-xr-xtest/913-heaps/run4
-rwxr-xr-xtest/914-hello-obsolescence/run4
-rwxr-xr-xtest/915-obsolete-2/run4
-rwxr-xr-xtest/916-obsolete-jit/run4
-rw-r--r--test/916-obsolete-jit/src/Main.java17
-rw-r--r--test/916-obsolete-jit/src/Transform.java8
-rwxr-xr-xtest/917-fields-transformation/run4
-rwxr-xr-xtest/918-fields/run4
-rwxr-xr-xtest/919-obsolete-fields/run4
-rw-r--r--test/919-obsolete-fields/src/Main.java7
-rw-r--r--test/919-obsolete-fields/src/Transform.java7
-rwxr-xr-xtest/920-objects/run4
-rw-r--r--test/921-hello-failure/expected.txt18
-rwxr-xr-xtest/921-hello-failure/run4
-rw-r--r--test/921-hello-failure/src/FieldChange.java61
-rw-r--r--test/921-hello-failure/src/Main.java6
-rw-r--r--test/921-hello-failure/src/MethodChange.java57
-rw-r--r--test/921-hello-failure/src/MissingField.java58
-rw-r--r--test/921-hello-failure/src/MissingMethod.java57
-rw-r--r--test/921-hello-failure/src/NewField.java60
-rw-r--r--test/921-hello-failure/src/NewMethod.java60
-rw-r--r--test/921-hello-failure/src/Transform3.java24
-rw-r--r--test/921-hello-failure/src/Transform4.java25
-rwxr-xr-xtest/922-properties/run4
-rwxr-xr-xtest/923-monitors/run4
-rwxr-xr-xtest/924-threads/run4
-rw-r--r--test/924-threads/src/Main.java17
-rwxr-xr-xtest/925-threadgroups/run4
-rw-r--r--test/925-threadgroups/src/Main.java21
-rwxr-xr-xtest/926-multi-obsolescence/run4
-rwxr-xr-xtest/927-timers/run4
-rwxr-xr-xtest/928-jni-table/run4
-rwxr-xr-xtest/929-search/run4
-rwxr-xr-xtest/930-hello-retransform/run4
-rwxr-xr-xtest/931-agent-thread/run4
-rwxr-xr-xtest/932-transform-saves/run4
-rwxr-xr-xtest/933-misc-events/run4
-rwxr-xr-xtest/934-load-transform/build17
-rw-r--r--test/934-load-transform/expected.txt1
-rw-r--r--test/934-load-transform/info.txt1
-rwxr-xr-xtest/934-load-transform/run17
-rw-r--r--test/934-load-transform/src-ex/TestMain.java21
-rw-r--r--test/934-load-transform/src-ex/Transform.java21
-rw-r--r--test/934-load-transform/src/Main.java95
-rwxr-xr-xtest/935-non-retransformable/build17
-rw-r--r--test/935-non-retransformable/expected.txt6
-rw-r--r--test/935-non-retransformable/info.txt1
-rwxr-xr-xtest/935-non-retransformable/run17
-rw-r--r--test/935-non-retransformable/src-ex/TestMain.java30
-rw-r--r--test/935-non-retransformable/src-ex/Transform.java21
-rw-r--r--test/935-non-retransformable/src/Main.java110
-rwxr-xr-xtest/936-search-onload/build17
-rw-r--r--test/936-search-onload/expected.txt3
-rw-r--r--test/936-search-onload/info.txt1
-rwxr-xr-xtest/936-search-onload/run21
-rw-r--r--test/936-search-onload/search_onload.cc63
-rw-r--r--test/936-search-onload/search_onload.h30
-rw-r--r--test/936-search-onload/src-ex/A.java18
-rw-r--r--test/936-search-onload/src/B.java18
-rw-r--r--test/936-search-onload/src/Main.java47
-rwxr-xr-xtest/937-hello-retransform-package/build17
-rw-r--r--test/937-hello-retransform-package/expected.txt2
-rw-r--r--test/937-hello-retransform-package/info.txt1
-rwxr-xr-xtest/937-hello-retransform-package/run17
-rw-r--r--test/937-hello-retransform-package/src/Main.java73
-rw-r--r--test/937-hello-retransform-package/src/Transform.java22
-rwxr-xr-xtest/938-load-transform-bcp/build17
-rw-r--r--test/938-load-transform-bcp/expected.txt2
-rw-r--r--test/938-load-transform-bcp/info.txt1
-rwxr-xr-xtest/938-load-transform-bcp/run17
-rw-r--r--test/938-load-transform-bcp/src-ex/TestMain.java35
-rw-r--r--test/938-load-transform-bcp/src/Main.java123
-rwxr-xr-xtest/939-hello-transformation-bcp/build17
-rw-r--r--test/939-hello-transformation-bcp/expected.txt3
-rw-r--r--test/939-hello-transformation-bcp/info.txt6
-rwxr-xr-xtest/939-hello-transformation-bcp/run17
-rw-r--r--test/939-hello-transformation-bcp/src/Main.java126
-rwxr-xr-xtest/940-recursive-obsolete/build17
-rw-r--r--test/940-recursive-obsolete/expected.txt21
-rw-r--r--test/940-recursive-obsolete/info.txt1
-rwxr-xr-xtest/940-recursive-obsolete/run17
-rw-r--r--test/940-recursive-obsolete/src/Main.java89
-rw-r--r--test/940-recursive-obsolete/src/Transform.java28
-rwxr-xr-xtest/941-recurive-obsolete-jit/build17
-rw-r--r--test/941-recurive-obsolete-jit/expected.txt22
-rw-r--r--test/941-recurive-obsolete-jit/info.txt1
-rwxr-xr-xtest/941-recurive-obsolete-jit/run17
-rw-r--r--test/941-recurive-obsolete-jit/src/Main.java155
-rw-r--r--test/941-recurive-obsolete-jit/src/Transform.java29
-rwxr-xr-xtest/942-private-recursive/build17
-rw-r--r--test/942-private-recursive/expected.txt21
-rw-r--r--test/942-private-recursive/info.txt1
-rwxr-xr-xtest/942-private-recursive/run17
-rw-r--r--test/942-private-recursive/src/Main.java94
-rw-r--r--test/942-private-recursive/src/Transform.java32
-rwxr-xr-xtest/943-private-recursive-jit/build17
-rw-r--r--test/943-private-recursive-jit/expected.txt22
-rw-r--r--test/943-private-recursive-jit/info.txt1
-rwxr-xr-xtest/943-private-recursive-jit/run17
-rw-r--r--test/943-private-recursive-jit/src/Main.java171
-rw-r--r--test/943-private-recursive-jit/src/Transform.java33
-rwxr-xr-xtest/944-transform-classloaders/build17
-rw-r--r--test/944-transform-classloaders/classloader.cc44
-rw-r--r--test/944-transform-classloaders/expected.txt5
-rw-r--r--test/944-transform-classloaders/info.txt7
-rwxr-xr-xtest/944-transform-classloaders/run17
-rw-r--r--test/944-transform-classloaders/src/CommonClassDefinition.java27
-rw-r--r--test/944-transform-classloaders/src/Main.java265
-rw-r--r--test/944-transform-classloaders/src/Transform.java28
-rw-r--r--test/944-transform-classloaders/src/Transform2.java21
-rw-r--r--test/956-methodhandles/src/Main.java126
-rw-r--r--test/957-methodhandle-transforms/expected.txt29
-rw-r--r--test/957-methodhandle-transforms/src/Main.java418
-rw-r--r--test/Android.bp6
-rw-r--r--test/Android.run-test.mk19
-rw-r--r--test/ErroneousInit/ErroneousInit.java23
-rw-r--r--test/Nested/Nested.java2
-rwxr-xr-xtest/etc/run-test-jar6
-rwxr-xr-xtest/run-test11
-rw-r--r--test/ti-agent/common_helper.cc107
-rw-r--r--test/ti-agent/common_helper.h5
-rw-r--r--test/ti-agent/common_load.cc12
176 files changed, 4776 insertions, 261 deletions
diff --git a/test/004-NativeAllocations/src/Main.java b/test/004-NativeAllocations/src/Main.java
index 92f4e21f40..8712755125 100644
--- a/test/004-NativeAllocations/src/Main.java
+++ b/test/004-NativeAllocations/src/Main.java
@@ -16,6 +16,7 @@
import java.lang.reflect.*;
import java.lang.Runtime;
+import dalvik.system.VMRuntime;
public class Main {
static Object nativeLock = new Object();
@@ -33,10 +34,19 @@ public class Main {
NativeAllocation(int bytes, boolean testingDeadlock) throws Exception {
this.bytes = bytes;
register_native_allocation.invoke(runtime, bytes);
+
+ // Register native allocation can only provide guarantees bounding
+ // the maximum outstanding allocations if finalizers don't time
+ // out. In case finalizers have timed out, wait longer for them
+ // now to complete so we can test the guarantees.
+ if (!testingDeadlock) {
+ VMRuntime.runFinalization(0);
+ }
+
synchronized (nativeLock) {
if (!testingDeadlock) {
nativeBytes += bytes;
- if (nativeBytes > maxMem) {
+ if (nativeBytes > 2 * maxMem) {
throw new OutOfMemoryError();
}
}
diff --git a/test/008-exceptions/expected.txt b/test/008-exceptions/expected.txt
index 083ecf7ced..fcf2ef49f3 100644
--- a/test/008-exceptions/expected.txt
+++ b/test/008-exceptions/expected.txt
@@ -1,11 +1,11 @@
Got an NPE: second throw
java.lang.NullPointerException: second throw
- at Main.catchAndRethrow(Main.java:77)
- at Main.exceptions_007(Main.java:59)
- at Main.main(Main.java:67)
+ at Main.catchAndRethrow(Main.java:94)
+ at Main.exceptions_007(Main.java:74)
+ at Main.main(Main.java:82)
Caused by: java.lang.NullPointerException: first throw
- at Main.throwNullPointerException(Main.java:84)
- at Main.catchAndRethrow(Main.java:74)
+ at Main.throwNullPointerException(Main.java:101)
+ at Main.catchAndRethrow(Main.java:91)
... 2 more
Static Init
BadError: This is bad by convention: BadInit
@@ -15,3 +15,11 @@ Static BadInitNoStringInit
BadErrorNoStringInit: This is bad by convention
java.lang.NoClassDefFoundError: BadInitNoStringInit
BadErrorNoStringInit: This is bad by convention
+BadSuperClass Static Init
+BadError: This is bad by convention: BadInit
+MultiDexBadInit Static Init
+java.lang.Error: MultiDexBadInit
+java.lang.NoClassDefFoundError: MultiDexBadInit
+ cause: java.lang.Error: MultiDexBadInit
+java.lang.NoClassDefFoundError: MultiDexBadInit
+ cause: java.lang.Error: MultiDexBadInit
diff --git a/test/008-exceptions/multidex.jpp b/test/008-exceptions/multidex.jpp
new file mode 100644
index 0000000000..a3746f5149
--- /dev/null
+++ b/test/008-exceptions/multidex.jpp
@@ -0,0 +1,27 @@
+BadError:
+ @@com.android.jack.annotations.ForceInMainDex
+ class BadError
+BadInit:
+ @@com.android.jack.annotations.ForceInMainDex
+ class BadInit
+BadErrorNoStringInit:
+ @@com.android.jack.annotations.ForceInMainDex
+ class BadErrorNoStringInit
+BadInitNoStringInit:
+ @@com.android.jack.annotations.ForceInMainDex
+ class BadInitNoStringInit
+BadSuperClass:
+ @@com.android.jack.annotations.ForceInMainDex
+ class BadSuperClass
+DerivedFromBadSuperClass:
+ @@com.android.jack.annotations.ForceInMainDex
+ class DerivedFromBadSuperClass
+Main:
+ @@com.android.jack.annotations.ForceInMainDex
+ class Main
+MultiDexBadInit:
+ @@com.android.jack.annotations.ForceInMainDex
+ class MultiDexBadInit
+MultiDexBadInitWrapper1:
+ @@com.android.jack.annotations.ForceInMainDex
+ class MultiDexBadInitWrapper1
diff --git a/test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java b/test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java
new file mode 100644
index 0000000000..f3953bd4c7
--- /dev/null
+++ b/test/008-exceptions/src-multidex/MultiDexBadInitWrapper2.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class MultiDexBadInitWrapper2 {
+ public static void setDummy(int value) {
+ if (doThrow) { throw new Error(); }
+ MultiDexBadInit.dummy = value;
+ }
+
+ public static boolean doThrow = false;
+}
diff --git a/test/008-exceptions/src/Main.java b/test/008-exceptions/src/Main.java
index b8231f12bd..74af00ccf7 100644
--- a/test/008-exceptions/src/Main.java
+++ b/test/008-exceptions/src/Main.java
@@ -50,6 +50,21 @@ class BadInitNoStringInit {
}
}
+// A class that throws BadError during static initialization, serving as a super class.
+class BadSuperClass {
+ static int dummy;
+ static {
+ System.out.println("BadSuperClass Static Init");
+ if (true) {
+ throw new BadError("BadInit");
+ }
+ }
+}
+
+// A class that derives from BadSuperClass.
+class DerivedFromBadSuperClass extends BadSuperClass {
+}
+
/**
* Exceptions across method calls
*/
@@ -63,10 +78,12 @@ public class Main {
npe.printStackTrace(System.out);
}
}
- public static void main (String args[]) {
+ public static void main(String args[]) {
exceptions_007();
exceptionsRethrowClassInitFailure();
exceptionsRethrowClassInitFailureNoStringInit();
+ exceptionsForSuperClassInitFailure();
+ exceptionsInMultiDex();
}
private static void catchAndRethrow() {
@@ -129,4 +146,70 @@ public class Main {
error.printStackTrace(System.out);
}
}
+
+ private static void exceptionsForSuperClassInitFailure() {
+ try {
+ // Resolve DerivedFromBadSuperClass.
+ BadSuperClass.dummy = 1;
+ throw new IllegalStateException("Should not reach here.");
+ } catch (BadError e) {
+ System.out.println(e);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ try {
+ // Before splitting mirror::Class::kStatusError into
+ // kStatusErrorUnresolved and kStatusErrorResolved,
+ // this would trigger a
+ // CHECK(super_class->IsResolved())
+ // failure in
+ // ClassLinker::LoadSuperAndInterfaces().
+ // After the change we're getting either VerifyError
+ // (for Optimizing) or NoClassDefFoundError wrapping
+ // BadError (for interpreter or JIT).
+ new DerivedFromBadSuperClass();
+ throw new IllegalStateException("Should not reach here.");
+ } catch (NoClassDefFoundError ncdfe) {
+ if (!(ncdfe.getCause() instanceof BadError)) {
+ ncdfe.getCause().printStackTrace();
+ }
+ } catch (VerifyError e) {
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ private static void exceptionsInMultiDex() {
+ try {
+ MultiDexBadInit.dummy = 1;
+ throw new IllegalStateException("Should not reach here.");
+ } catch (Error e) {
+ System.out.println(e);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ // Before splitting mirror::Class::kStatusError into
+ // kStatusErrorUnresolved and kStatusErrorResolved,
+ // the exception from wrapper 1 would have been
+ // wrapped in NoClassDefFoundError but the exception
+ // from wrapper 2 would have been unwrapped.
+ try {
+ MultiDexBadInitWrapper1.setDummy(1);
+ throw new IllegalStateException("Should not reach here.");
+ } catch (NoClassDefFoundError ncdfe) {
+ System.out.println(ncdfe);
+ System.out.println(" cause: " + ncdfe.getCause());
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ try {
+ MultiDexBadInitWrapper2.setDummy(1);
+ throw new IllegalStateException("Should not reach here.");
+ } catch (NoClassDefFoundError ncdfe) {
+ System.out.println(ncdfe);
+ System.out.println(" cause: " + ncdfe.getCause());
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
}
diff --git a/test/008-exceptions/src/MultiDexBadInit.java b/test/008-exceptions/src/MultiDexBadInit.java
new file mode 100644
index 0000000000..e3ebb9ca45
--- /dev/null
+++ b/test/008-exceptions/src/MultiDexBadInit.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class MultiDexBadInit {
+ static int dummy;
+ static {
+ System.out.println("MultiDexBadInit Static Init");
+ if (true) {
+ throw new Error("MultiDexBadInit");
+ }
+ }
+}
diff --git a/test/008-exceptions/src/MultiDexBadInitWrapper1.java b/test/008-exceptions/src/MultiDexBadInitWrapper1.java
new file mode 100644
index 0000000000..059e6a3d7d
--- /dev/null
+++ b/test/008-exceptions/src/MultiDexBadInitWrapper1.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class MultiDexBadInitWrapper1 {
+ public static void setDummy(int value) {
+ if (doThrow) { throw new Error(); }
+ MultiDexBadInit.dummy = value;
+ }
+
+ public static boolean doThrow = false;
+}
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index 06f193af32..072f0e68ee 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -535,6 +535,8 @@ public class Main {
Assert.assertEquals(Math.min(0.0f, Float.MAX_VALUE), 0.0f);
Assert.assertEquals(Math.min(Float.MIN_VALUE, 0.0f), 0.0f);
Assert.assertEquals(Math.min(Float.MIN_VALUE, Float.MAX_VALUE), Float.MIN_VALUE);
+ // Should not have flush-to-zero behavior.
+ Assert.assertEquals(Math.min(Float.MIN_VALUE, Float.MIN_VALUE), Float.MIN_VALUE);
}
public static void test_Math_max_F() {
@@ -548,8 +550,10 @@ public class Main {
Assert.assertEquals(Math.max(1.0f, 0.0f), 1.0f);
Assert.assertEquals(Math.max(0.0f, 1.0f), 1.0f);
Assert.assertEquals(Math.max(0.0f, Float.MAX_VALUE), Float.MAX_VALUE);
- Assert.assertEquals(Math.max(Float.MIN_VALUE, 0.0f), Float.MIN_VALUE);
Assert.assertEquals(Math.max(Float.MIN_VALUE, Float.MAX_VALUE), Float.MAX_VALUE);
+ // Should not have flush-to-zero behavior.
+ Assert.assertEquals(Math.max(Float.MIN_VALUE, 0.0f), Float.MIN_VALUE);
+ Assert.assertEquals(Math.max(Float.MIN_VALUE, Float.MIN_VALUE), Float.MIN_VALUE);
}
public static void test_Math_min_D() {
@@ -565,6 +569,8 @@ public class Main {
Assert.assertEquals(Math.min(0.0d, Double.MAX_VALUE), 0.0d);
Assert.assertEquals(Math.min(Double.MIN_VALUE, 0.0d), 0.0d);
Assert.assertEquals(Math.min(Double.MIN_VALUE, Double.MAX_VALUE), Double.MIN_VALUE);
+ // Should not have flush-to-zero behavior.
+ Assert.assertEquals(Math.min(Double.MIN_VALUE, Double.MIN_VALUE), Double.MIN_VALUE);
}
public static void test_Math_max_D() {
@@ -580,6 +586,9 @@ public class Main {
Assert.assertEquals(Math.max(0.0d, Double.MAX_VALUE), Double.MAX_VALUE);
Assert.assertEquals(Math.max(Double.MIN_VALUE, 0.0d), Double.MIN_VALUE);
Assert.assertEquals(Math.max(Double.MIN_VALUE, Double.MAX_VALUE), Double.MAX_VALUE);
+ // Should not have flush-to-zero behavior.
+ Assert.assertEquals(Math.max(Double.MIN_VALUE, 0.0d), Double.MIN_VALUE);
+ Assert.assertEquals(Math.max(Double.MIN_VALUE, Double.MIN_VALUE), Double.MIN_VALUE);
}
public static void test_Math_sqrt() {
@@ -730,16 +739,19 @@ public class Main {
Math.rint(+2.1);
Assert.assertEquals(Math.rint(+0.0), +0.0d, 0.0);
Assert.assertEquals(Math.rint(-0.0), -0.0d, 0.0);
+ Assert.assertEquals(Math.rint(+0.5), +0.0d, 0.0); // expects tie-to-even
Assert.assertEquals(Math.rint(+2.0), +2.0d, 0.0);
Assert.assertEquals(Math.rint(+2.1), +2.0d, 0.0);
- Assert.assertEquals(Math.rint(+2.5), +2.0d, 0.0);
+ Assert.assertEquals(Math.rint(+2.5), +2.0d, 0.0); // expects tie-to-even
Assert.assertEquals(Math.rint(+2.9), +3.0d, 0.0);
Assert.assertEquals(Math.rint(+3.0), +3.0d, 0.0);
+ Assert.assertEquals(Math.rint(+3.5), +4.0d, 0.0); // expects tie-to-even
Assert.assertEquals(Math.rint(-2.0), -2.0d, 0.0);
Assert.assertEquals(Math.rint(-2.1), -2.0d, 0.0);
- Assert.assertEquals(Math.rint(-2.5), -2.0d, 0.0);
+ Assert.assertEquals(Math.rint(-2.5), -2.0d, 0.0); // expects tie-to-even
Assert.assertEquals(Math.rint(-2.9), -3.0d, 0.0);
Assert.assertEquals(Math.rint(-3.0), -3.0d, 0.0);
+ Assert.assertEquals(Math.rint(-3.5), -4.0d, 0.0); // expects tie-to-even
// 2^52 - 1.5
Assert.assertEquals(Math.rint(Double.longBitsToDouble(0x432FFFFFFFFFFFFDl)),
Double.longBitsToDouble(0x432FFFFFFFFFFFFCl), 0.0);
diff --git a/test/142-classloader2/expected.txt b/test/142-classloader2/expected.txt
index 86f5e220e2..056d9785de 100644
--- a/test/142-classloader2/expected.txt
+++ b/test/142-classloader2/expected.txt
@@ -1 +1,5 @@
+Loaded class B.
+Caught VerifyError.
+Loaded class B.
+Caught wrapped VerifyError.
Everything OK.
diff --git a/test/142-classloader2/src/Main.java b/test/142-classloader2/src/Main.java
index 80b00e7dd2..a0c77645a3 100644
--- a/test/142-classloader2/src/Main.java
+++ b/test/142-classloader2/src/Main.java
@@ -74,16 +74,25 @@ public class Main {
// Try to load a dex file with bad dex code. Use new instance to force verification.
try {
Class<?> badClass = Main.class.getClassLoader().loadClass("B");
+ System.out.println("Loaded class B.");
badClass.newInstance();
- System.out.println("Should not be able to load class from bad dex file.");
+ System.out.println("Should not be able to instantiate B with bad dex bytecode.");
} catch (VerifyError e) {
+ System.out.println("Caught VerifyError.");
}
// Make sure the same error is rethrown when reloading the bad class.
try {
Class<?> badClass = Main.class.getClassLoader().loadClass("B");
- System.out.println("Should not be able to load class from bad dex file.");
- } catch (VerifyError e) {
+ System.out.println("Loaded class B.");
+ badClass.newInstance();
+ System.out.println("Should not be able to instantiate B with bad dex bytecode.");
+ } catch (NoClassDefFoundError e) {
+ if (e.getCause() instanceof VerifyError) {
+ System.out.println("Caught wrapped VerifyError.");
+ } else {
+ e.printStackTrace();
+ }
}
System.out.println("Everything OK.");
diff --git a/test/154-gc-loop/expected.txt b/test/154-gc-loop/expected.txt
new file mode 100644
index 0000000000..6106818c79
--- /dev/null
+++ b/test/154-gc-loop/expected.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+Finalize count too large: false
diff --git a/test/154-gc-loop/heap_interface.cc b/test/154-gc-loop/heap_interface.cc
new file mode 100644
index 0000000000..8d610a87fa
--- /dev/null
+++ b/test/154-gc-loop/heap_interface.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "gc/heap.h"
+#include "runtime.h"
+
+namespace art {
+namespace {
+
+extern "C" JNIEXPORT void JNICALL Java_Main_backgroundProcessState(JNIEnv*, jclass) {
+ Runtime::Current()->UpdateProcessState(kProcessStateJankImperceptible);
+}
+
+} // namespace
+} // namespace art
diff --git a/test/154-gc-loop/info.txt b/test/154-gc-loop/info.txt
new file mode 100644
index 0000000000..f599db1d01
--- /dev/null
+++ b/test/154-gc-loop/info.txt
@@ -0,0 +1 @@
+Test that GC doesn't happen too often for a few small allocations.
diff --git a/test/154-gc-loop/src/Main.java b/test/154-gc-loop/src/Main.java
new file mode 100644
index 0000000000..3a256c109e
--- /dev/null
+++ b/test/154-gc-loop/src/Main.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 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.ref.WeakReference;
+
+public class Main {
+ static final class GcWatcher {
+ protected void finalize() throws Throwable {
+ watcher = new WeakReference<GcWatcher>(new GcWatcher());
+ ++finalizeCounter;
+ }
+ }
+ static WeakReference<GcWatcher> watcher = new WeakReference<GcWatcher>(new GcWatcher());
+ static Object o = new Object();
+ static int finalizeCounter = 0;
+
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+ backgroundProcessState();
+ try {
+ Runtime.getRuntime().gc();
+ for (int i = 0; i < 10; ++i) {
+ o = new Object();
+ Thread.sleep(1000);
+ }
+ } catch (Exception e) {}
+ System.out.println("Finalize count too large: " +
+ ((finalizeCounter >= 10) ? Integer.toString(finalizeCounter) : "false"));
+ }
+
+ private static native void backgroundProcessState();
+}
diff --git a/test/466-get-live-vreg/get_live_vreg_jni.cc b/test/466-get-live-vreg/get_live_vreg_jni.cc
index d3a033b12a..6cea673b41 100644
--- a/test/466-get-live-vreg/get_live_vreg_jni.cc
+++ b/test/466-get-live-vreg/get_live_vreg_jni.cc
@@ -47,7 +47,7 @@ class TestVisitor : public StackVisitor {
uint32_t value = 0;
if (GetCurrentQuickFrame() != nullptr &&
GetCurrentOatQuickMethodHeader()->IsOptimized() &&
- !Runtime::Current()->IsDebuggable()) {
+ !Runtime::Current()->IsJavaDebuggable()) {
CHECK_EQ(GetVReg(m, dex_register_of_first_parameter, kIntVReg, &value), false);
} else {
CHECK(GetVReg(m, dex_register_of_first_parameter, kIntVReg, &value));
diff --git a/test/482-checker-loop-back-edge-use/src/Main.java b/test/482-checker-loop-back-edge-use/src/Main.java
index 65dfd411fd..86977d1b8e 100644
--- a/test/482-checker-loop-back-edge-use/src/Main.java
+++ b/test/482-checker-loop-back-edge-use/src/Main.java
@@ -164,6 +164,12 @@ public class Main {
}
}
+
+ static boolean $opt$noinline$ensureSideEffects() {
+ if (doThrow) throw new Error("");
+ return true;
+ }
+
/// CHECK-START: void Main.loop9() liveness (after)
/// CHECK: <<Arg:z\d+>> StaticFieldGet liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
/// CHECK: If [<<Arg>>] liveness:<<IfLiv:\d+>>
@@ -178,7 +184,7 @@ public class Main {
// Add some code at entry to avoid having the entry block be a pre header.
// This avoids having to create a synthesized block.
System.out.println("Enter");
- while (Runtime.getRuntime() != null) {
+ while ($opt$noinline$ensureSideEffects()) {
// 'incoming' must only have a use in the inner loop.
boolean incoming = field;
while (incoming) {}
@@ -189,4 +195,5 @@ public class Main {
}
static boolean field;
+ static boolean doThrow = false;
}
diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java
index db437686f0..dd77423870 100644
--- a/test/552-checker-sharpening/src/Main.java
+++ b/test/552-checker-sharpening/src/Main.java
@@ -52,7 +52,6 @@ public class Main {
/// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
/// CHECK-START-MIPS: int Main.testSimple(int) sharpening (after)
- /// CHECK-NOT: MipsDexCacheArraysBase
/// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
/// CHECK-START-MIPS64: int Main.testSimple(int) sharpening (after)
@@ -69,10 +68,6 @@ public class Main {
/// CHECK: ArmDexCacheArraysBase
/// CHECK-NOT: ArmDexCacheArraysBase
- /// CHECK-START-MIPS: int Main.testSimple(int) dex_cache_array_fixups_mips (after)
- /// CHECK: MipsDexCacheArraysBase
- /// CHECK-NOT: MipsDexCacheArraysBase
-
/// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after)
/// CHECK: X86ComputeBaseMethodAddress
/// CHECK-NOT: X86ComputeBaseMethodAddress
@@ -95,7 +90,6 @@ public class Main {
/// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
/// CHECK-START-MIPS: int Main.testDiamond(boolean, int) sharpening (after)
- /// CHECK-NOT: MipsDexCacheArraysBase
/// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
/// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
@@ -120,14 +114,6 @@ public class Main {
/// CHECK: ArmDexCacheArraysBase
/// CHECK-NEXT: If
- /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) dex_cache_array_fixups_mips (after)
- /// CHECK: MipsDexCacheArraysBase
- /// CHECK-NOT: MipsDexCacheArraysBase
-
- /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) dex_cache_array_fixups_mips (after)
- /// CHECK: MipsDexCacheArraysBase
- /// CHECK-NEXT: If
-
/// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after)
/// CHECK: X86ComputeBaseMethodAddress
/// CHECK-NOT: X86ComputeBaseMethodAddress
@@ -182,24 +168,6 @@ public class Main {
/// CHECK: begin_block
/// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
- /// CHECK-START-MIPS: int Main.testLoop(int[], int) dex_cache_array_fixups_mips (before)
- /// CHECK-NOT: MipsDexCacheArraysBase
-
- /// CHECK-START-MIPS: int Main.testLoop(int[], int) dex_cache_array_fixups_mips (after)
- /// CHECK: MipsDexCacheArraysBase
- /// CHECK-NOT: MipsDexCacheArraysBase
-
- /// CHECK-START-MIPS: int Main.testLoop(int[], int) dex_cache_array_fixups_mips (after)
- /// CHECK: InvokeStaticOrDirect
- /// CHECK-NOT: InvokeStaticOrDirect
-
- /// CHECK-START-MIPS: int Main.testLoop(int[], int) dex_cache_array_fixups_mips (after)
- /// CHECK: ArrayLength
- /// CHECK-NEXT: MipsDexCacheArraysBase
- /// CHECK-NEXT: Goto
- /// CHECK: begin_block
- /// CHECK: InvokeStaticOrDirect method_load_kind:dex_cache_pc_relative
-
public static int testLoop(int[] array, int x) {
// PC-relative bases used by ARM, MIPS and X86 should be pulled before the loop.
for (int i : array) {
@@ -228,16 +196,6 @@ public class Main {
/// CHECK-NEXT: ArmDexCacheArraysBase
/// CHECK-NEXT: Goto
- /// CHECK-START-MIPS: int Main.testLoopWithDiamond(int[], boolean, int) dex_cache_array_fixups_mips (before)
- /// CHECK-NOT: MipsDexCacheArraysBase
-
- /// CHECK-START-MIPS: int Main.testLoopWithDiamond(int[], boolean, int) dex_cache_array_fixups_mips (after)
- /// CHECK: If
- /// CHECK: begin_block
- /// CHECK: ArrayLength
- /// CHECK-NEXT: MipsDexCacheArraysBase
- /// CHECK-NEXT: Goto
-
public static int testLoopWithDiamond(int[] array, boolean negate, int x) {
// PC-relative bases used by ARM, MIPS and X86 should be pulled before the loop
// but not outside the if.
@@ -325,9 +283,6 @@ public class Main {
return "non-boot-image-string";
}
- /// CHECK-START: java.lang.Class Main.$noinline$getStringClass() sharpening (before)
- /// CHECK: LoadClass load_kind:DexCacheViaMethod class_name:java.lang.String
-
/// CHECK-START-X86: java.lang.Class Main.$noinline$getStringClass() sharpening (after)
// Note: load kind depends on PIC/non-PIC
// TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress.
@@ -365,9 +320,6 @@ public class Main {
return String.class;
}
- /// CHECK-START: java.lang.Class Main.$noinline$getOtherClass() sharpening (before)
- /// CHECK: LoadClass load_kind:DexCacheViaMethod class_name:Other
-
/// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
/// CHECK: LoadClass load_kind:BssEntry class_name:Other
@@ -381,20 +333,12 @@ public class Main {
/// CHECK-START-ARM: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
/// CHECK: LoadClass load_kind:BssEntry class_name:Other
- /// CHECK-START-ARM: java.lang.Class Main.$noinline$getOtherClass() dex_cache_array_fixups_arm (after)
- /// CHECK-DAG: ArmDexCacheArraysBase
- /// CHECK-DAG: LoadClass load_kind:BssEntry class_name:Other
-
/// CHECK-START-ARM64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
/// CHECK: LoadClass load_kind:BssEntry class_name:Other
/// CHECK-START-MIPS: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
/// CHECK: LoadClass load_kind:BssEntry class_name:Other
- /// CHECK-START-MIPS: java.lang.Class Main.$noinline$getOtherClass() dex_cache_array_fixups_mips (after)
- /// CHECK-DAG: MipsDexCacheArraysBase
- /// CHECK-DAG: LoadClass load_kind:BssEntry class_name:Other
-
/// CHECK-START-MIPS64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
/// CHECK: LoadClass load_kind:BssEntry class_name:Other
diff --git a/test/616-cha-abstract/expected.txt b/test/616-cha-abstract/expected.txt
new file mode 100644
index 0000000000..6a5618ebc6
--- /dev/null
+++ b/test/616-cha-abstract/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/616-cha-abstract/info.txt b/test/616-cha-abstract/info.txt
new file mode 100644
index 0000000000..4f7e01391d
--- /dev/null
+++ b/test/616-cha-abstract/info.txt
@@ -0,0 +1 @@
+Test for Class Hierarchy Analysis (CHA) on abstract method.
diff --git a/test/616-cha-abstract/run b/test/616-cha-abstract/run
new file mode 100644
index 0000000000..d8b4f0d26c
--- /dev/null
+++ b/test/616-cha-abstract/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 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.
+
+# Run without an app image to prevent the classes to be loaded at startup.
+exec ${RUN} "${@}" --no-app-image
diff --git a/test/616-cha-abstract/src/Main.java b/test/616-cha-abstract/src/Main.java
new file mode 100644
index 0000000000..e1d7db170d
--- /dev/null
+++ b/test/616-cha-abstract/src/Main.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+abstract class Base {
+ abstract void foo(int i);
+
+ void printError(String msg) {
+ System.out.println(msg);
+ }
+}
+
+class Main1 extends Base {
+ void foo(int i) {
+ if (i != 1) {
+ printError("error1");
+ }
+ }
+}
+
+class Main2 extends Main1 {
+ void foo(int i) {
+ if (i != 2) {
+ printError("error2");
+ }
+ }
+}
+
+public class Main {
+ static Main1 sMain1;
+ static Main1 sMain2;
+
+ static boolean sIsOptimizing = true;
+ static boolean sHasJIT = true;
+ static volatile boolean sOtherThreadStarted;
+
+ private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
+ if (hasSingleImplementation(clazz, method_name) != b) {
+ System.out.println(clazz + "." + method_name +
+ " doesn't have single implementation value of " + b);
+ }
+ }
+
+ // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
+ // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
+ // After Dummy.createMain2() which links in Main2, live testOverride() on stack
+ // should be deoptimized.
+ static void testOverride(boolean createMain2, boolean wait, boolean setHasJIT) {
+ if (setHasJIT) {
+ if (isInterpreted()) {
+ sHasJIT = false;
+ }
+ return;
+ }
+
+ if (createMain2 && (sIsOptimizing || sHasJIT)) {
+ assertIsManaged();
+ }
+
+ sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
+
+ if (createMain2) {
+ // Wait for the other thread to start.
+ while (!sOtherThreadStarted);
+ // Create an Main2 instance and assign it to sMain2.
+ // sMain1 is kept the same.
+ sMain2 = Dummy.createMain2();
+ // Wake up the other thread.
+ synchronized(Main.class) {
+ Main.class.notify();
+ }
+ } else if (wait) {
+ // This is the other thread.
+ synchronized(Main.class) {
+ sOtherThreadStarted = true;
+ // Wait for Main2 to be linked and deoptimization is triggered.
+ try {
+ Main.class.wait();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ // There should be a deoptimization here right after Main2 is linked by
+ // calling Dummy.createMain2(), even though sMain1 didn't change.
+ // The behavior here would be different if inline-cache is used, which
+ // doesn't deoptimize since sMain1 still hits the type cache.
+ sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
+ if ((createMain2 || wait) && sHasJIT && !sIsOptimizing) {
+ // This method should be deoptimized right after Main2 is created.
+ assertIsInterpreted();
+ }
+
+ if (sMain2 != null) {
+ sMain2.foo(sMain2.getClass() == Main1.class ? 1 : 2);
+ }
+ }
+
+ // Test scenarios under which CHA-based devirtualization happens,
+ // and class loading that overrides a method can invalidate compiled code.
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+
+ if (isInterpreted()) {
+ sIsOptimizing = false;
+ }
+
+ // sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
+ sMain1 = new Main1();
+
+ ensureJitCompiled(Main.class, "testOverride");
+ testOverride(false, false, true);
+
+ if (sHasJIT && !sIsOptimizing) {
+ assertSingleImplementation(Base.class, "foo", true);
+ assertSingleImplementation(Main1.class, "foo", true);
+ } else {
+ // Main2 is verified ahead-of-time so it's linked in already.
+ }
+
+ // Create another thread that also calls sMain1.foo().
+ // Try to test suspend and deopt another thread.
+ new Thread() {
+ public void run() {
+ testOverride(false, true, false);
+ }
+ }.start();
+
+ // This will create Main2 instance in the middle of testOverride().
+ testOverride(true, false, false);
+ assertSingleImplementation(Base.class, "foo", false);
+ assertSingleImplementation(Main1.class, "foo", false);
+ }
+
+ private static native void ensureJitCompiled(Class<?> itf, String method_name);
+ private static native void assertIsInterpreted();
+ private static native void assertIsManaged();
+ private static native boolean isInterpreted();
+ private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
+}
+
+// Put createMain2() in another class to avoid class loading due to verifier.
+class Dummy {
+ static Main1 createMain2() {
+ return new Main2();
+ }
+}
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index 7cc0b8b652..7509d9b4f3 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -154,8 +154,8 @@ public class Main {
/// CHECK-NOT: Phi
//
/// CHECK-START: int Main.polynomialInt() instruction_simplifier$after_bce (after)
- /// CHECK-DAG: <<Int:i\d+>> IntConstant -45 loop:none
- /// CHECK-DAG: Return [<<Int>>] loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant -45 loop:none
+ /// CHECK-DAG: Return [<<Int>>] loop:none
static int polynomialInt() {
int x = 0;
for (int i = 0; i < 10; i++) {
@@ -164,6 +164,81 @@ public class Main {
return x;
}
+ // Regression test for b/34779592 (found with fuzz testing): overflow for last value
+ // of division truncates to zero, for multiplication it simply truncates.
+ //
+ /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ //
+ /// CHECK-START: int Main.geoIntDivLastValue(int) instruction_simplifier$after_bce (after)
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: Return [<<Int>>] loop:none
+ static int geoIntDivLastValue(int x) {
+ for (int i = 0; i < 2; i++) {
+ x /= 1081788608;
+ }
+ return x;
+ }
+
+ /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ //
+ /// CHECK-START: int Main.geoIntMulLastValue(int) instruction_simplifier$after_bce (after)
+ /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant -194211840 loop:none
+ /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>] loop:none
+ /// CHECK-DAG: Return [<<Mul>>] loop:none
+ static int geoIntMulLastValue(int x) {
+ for (int i = 0; i < 2; i++) {
+ x *= 1081788608;
+ }
+ return x;
+ }
+
+ /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ //
+ /// CHECK-START: long Main.geoLongDivLastValue(long) instruction_simplifier$after_bce (after)
+ /// CHECK-DAG: <<Long:j\d+>> LongConstant 0 loop:none
+ /// CHECK-DAG: Return [<<Long>>] loop:none
+ static long geoLongDivLastValue(long x) {
+ for (int i = 0; i < 10; i++) {
+ x /= 1081788608;
+ }
+ return x;
+ }
+
+ /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ //
+ /// CHECK-START: long Main.geoLongMulLastValue(long) instruction_simplifier$after_bce (after)
+ /// CHECK-DAG: <<Par:j\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Long:j\d+>> LongConstant -8070450532247928832 loop:none
+ /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Par>>,<<Long>>] loop:none
+ /// CHECK-DAG: Return [<<Mul>>] loop:none
+ static long geoLongMulLastValue(long x) {
+ for (int i = 0; i < 10; i++) {
+ x *= 1081788608;
+ }
+ return x;
+ }
+
public static void main(String[] args) {
expectEquals(10, earlyExitFirst(-1));
for (int i = 0; i <= 10; i++) {
@@ -185,6 +260,42 @@ public class Main {
expectEquals(-45, polynomialIntFromLong());
expectEquals(-45, polynomialInt());
+ expectEquals(0, geoIntDivLastValue(0));
+ expectEquals(0, geoIntDivLastValue(1));
+ expectEquals(0, geoIntDivLastValue(2));
+ expectEquals(0, geoIntDivLastValue(1081788608));
+ expectEquals(0, geoIntDivLastValue(-1081788608));
+ expectEquals(0, geoIntDivLastValue(2147483647));
+ expectEquals(0, geoIntDivLastValue(-2147483648));
+
+ expectEquals( 0, geoIntMulLastValue(0));
+ expectEquals( -194211840, geoIntMulLastValue(1));
+ expectEquals( -388423680, geoIntMulLastValue(2));
+ expectEquals(-1041498112, geoIntMulLastValue(1081788608));
+ expectEquals( 1041498112, geoIntMulLastValue(-1081788608));
+ expectEquals( 194211840, geoIntMulLastValue(2147483647));
+ expectEquals( 0, geoIntMulLastValue(-2147483648));
+
+ expectEquals(0L, geoLongDivLastValue(0L));
+ expectEquals(0L, geoLongDivLastValue(1L));
+ expectEquals(0L, geoLongDivLastValue(2L));
+ expectEquals(0L, geoLongDivLastValue(1081788608L));
+ expectEquals(0L, geoLongDivLastValue(-1081788608L));
+ expectEquals(0L, geoLongDivLastValue(2147483647L));
+ expectEquals(0L, geoLongDivLastValue(-2147483648L));
+ expectEquals(0L, geoLongDivLastValue(9223372036854775807L));
+ expectEquals(0L, geoLongDivLastValue(-9223372036854775808L));
+
+ expectEquals( 0L, geoLongMulLastValue(0L));
+ expectEquals(-8070450532247928832L, geoLongMulLastValue(1L));
+ expectEquals( 2305843009213693952L, geoLongMulLastValue(2L));
+ expectEquals( 0L, geoLongMulLastValue(1081788608L));
+ expectEquals( 0L, geoLongMulLastValue(-1081788608L));
+ expectEquals( 8070450532247928832L, geoLongMulLastValue(2147483647L));
+ expectEquals( 0L, geoLongMulLastValue(-2147483648L));
+ expectEquals( 8070450532247928832L, geoLongMulLastValue(9223372036854775807L));
+ expectEquals( 0L, geoLongMulLastValue(-9223372036854775808L));
+
System.out.println("passed");
}
@@ -193,4 +304,10 @@ public class Main {
throw new Error("Expected: " + expected + ", found: " + result);
}
}
+
+ private static void expectEquals(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
}
diff --git a/test/626-checker-arm64-scratch-register/src/Main.java b/test/626-checker-arm64-scratch-register/src/Main.java
index aa211be33c..6dd4374116 100644
--- a/test/626-checker-arm64-scratch-register/src/Main.java
+++ b/test/626-checker-arm64-scratch-register/src/Main.java
@@ -95,8 +95,8 @@ public class Main {
/// CHECK: str s1, [sp, #28]
/// CHECK: ldr s1, [sp, #32]
/// CHECK: str s31, [sp, #32]
- /// CHECK: ldr w16, [sp, #20]
- /// CHECK: str w16, [sp, #40]
+ /// CHECK: ldr s31, [sp, #20]
+ /// CHECK: str s31, [sp, #40]
/// CHECK: str s12, [sp, #20]
/// CHECK: fmov d12, d11
/// CHECK: fmov d11, d10
diff --git a/test/626-const-class-linking/clear_dex_cache_types.cc b/test/626-const-class-linking/clear_dex_cache_types.cc
index b035896166..c0aedc199f 100644
--- a/test/626-const-class-linking/clear_dex_cache_types.cc
+++ b/test/626-const-class-linking/clear_dex_cache_types.cc
@@ -15,6 +15,9 @@
*/
#include "jni.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
+#include "mirror/dex_cache-inl.h"
#include "object_lock.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/test/635-checker-arm64-volatile-load-cc/expected.txt b/test/635-checker-arm64-volatile-load-cc/expected.txt
new file mode 100644
index 0000000000..b0aad4deb5
--- /dev/null
+++ b/test/635-checker-arm64-volatile-load-cc/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/635-checker-arm64-volatile-load-cc/info.txt b/test/635-checker-arm64-volatile-load-cc/info.txt
new file mode 100644
index 0000000000..5d67df4a19
--- /dev/null
+++ b/test/635-checker-arm64-volatile-load-cc/info.txt
@@ -0,0 +1,3 @@
+Regression test checking that the VIXL ARM64 scratch register pool is
+not exhausted when generating a volatile field load with a large
+offset with (Baker) read barriers (b/34726333).
diff --git a/test/635-checker-arm64-volatile-load-cc/src/Main.java b/test/635-checker-arm64-volatile-load-cc/src/Main.java
new file mode 100644
index 0000000000..6a26e940ac
--- /dev/null
+++ b/test/635-checker-arm64-volatile-load-cc/src/Main.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+public class Main {
+
+ static volatile Object s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
+ static volatile Object s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
+ static volatile Object s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
+ static volatile Object s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
+ static volatile Object s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
+ static volatile Object s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
+ static volatile Object s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
+ static volatile Object s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
+ static volatile Object s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
+ static volatile Object s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
+
+ static volatile Object s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
+ static volatile Object s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
+ static volatile Object s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
+ static volatile Object s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
+ static volatile Object s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
+ static volatile Object s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
+ static volatile Object s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
+ static volatile Object s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
+ static volatile Object s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
+ static volatile Object s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
+
+ static volatile Object s200, s201, s202, s203, s204, s205, s206, s207, s208, s209;
+ static volatile Object s210, s211, s212, s213, s214, s215, s216, s217, s218, s219;
+ static volatile Object s220, s221, s222, s223, s224, s225, s226, s227, s228, s229;
+ static volatile Object s230, s231, s232, s233, s234, s235, s236, s237, s238, s239;
+ static volatile Object s240, s241, s242, s243, s244, s245, s246, s247, s248, s249;
+ static volatile Object s250, s251, s252, s253, s254, s255, s256, s257, s258, s259;
+ static volatile Object s260, s261, s262, s263, s264, s265, s266, s267, s268, s269;
+ static volatile Object s270, s271, s272, s273, s274, s275, s276, s277, s278, s279;
+ static volatile Object s280, s281, s282, s283, s284, s285, s286, s287, s288, s289;
+ static volatile Object s290, s291, s292, s293, s294, s295, s296, s297, s298, s299;
+
+ static volatile Object s300, s301, s302, s303, s304, s305, s306, s307, s308, s309;
+ static volatile Object s310, s311, s312, s313, s314, s315, s316, s317, s318, s319;
+ static volatile Object s320, s321, s322, s323, s324, s325, s326, s327, s328, s329;
+ static volatile Object s330, s331, s332, s333, s334, s335, s336, s337, s338, s339;
+ static volatile Object s340, s341, s342, s343, s344, s345, s346, s347, s348, s349;
+ static volatile Object s350, s351, s352, s353, s354, s355, s356, s357, s358, s359;
+ static volatile Object s360, s361, s362, s363, s364, s365, s366, s367, s368, s369;
+ static volatile Object s370, s371, s372, s373, s374, s375, s376, s377, s378, s379;
+ static volatile Object s380, s381, s382, s383, s384, s385, s386, s387, s388, s389;
+ static volatile Object s390, s391, s392, s393, s394, s395, s396, s397, s398, s399;
+
+ static volatile Object s400, s401, s402, s403, s404, s405, s406, s407, s408, s409;
+ static volatile Object s410, s411, s412, s413, s414, s415, s416, s417, s418, s419;
+ static volatile Object s420, s421, s422, s423, s424, s425, s426, s427, s428, s429;
+ static volatile Object s430, s431, s432, s433, s434, s435, s436, s437, s438, s439;
+ static volatile Object s440, s441, s442, s443, s444, s445, s446, s447, s448, s449;
+ static volatile Object s450, s451, s452, s453, s454, s455, s456, s457, s458, s459;
+ static volatile Object s460, s461, s462, s463, s464, s465, s466, s467, s468, s469;
+ static volatile Object s470, s471, s472, s473, s474, s475, s476, s477, s478, s479;
+ static volatile Object s480, s481, s482, s483, s484, s485, s486, s487, s488, s489;
+ static volatile Object s490, s491, s492, s493, s494, s495, s496, s497, s498, s499;
+
+ static volatile Object s500, s501, s502, s503, s504, s505, s506, s507, s508, s509;
+ static volatile Object s510, s511, s512, s513, s514, s515, s516, s517, s518, s519;
+ static volatile Object s520, s521, s522, s523, s524, s525, s526, s527, s528, s529;
+ static volatile Object s530, s531, s532, s533, s534, s535, s536, s537, s538, s539;
+ static volatile Object s540, s541, s542, s543, s544, s545, s546, s547, s548, s549;
+ static volatile Object s550, s551, s552, s553, s554, s555, s556, s557, s558, s559;
+ static volatile Object s560, s561, s562, s563, s564, s565, s566, s567, s568, s569;
+ static volatile Object s570, s571, s572, s573, s574, s575, s576, s577, s578, s579;
+ static volatile Object s580, s581, s582, s583, s584, s585, s586, s587, s588, s589;
+ static volatile Object s590, s591, s592, s593, s594, s595, s596, s597, s598, s599;
+
+ static volatile Object s600, s601, s602, s603, s604, s605, s606, s607, s608, s609;
+ static volatile Object s610, s611, s612, s613, s614, s615, s616, s617, s618, s619;
+ static volatile Object s620, s621, s622, s623, s624, s625, s626, s627, s628, s629;
+ static volatile Object s630, s631, s632, s633, s634, s635, s636, s637, s638, s639;
+ static volatile Object s640, s641, s642, s643, s644, s645, s646, s647, s648, s649;
+ static volatile Object s650, s651, s652, s653, s654, s655, s656, s657, s658, s659;
+ static volatile Object s660, s661, s662, s663, s664, s665, s666, s667, s668, s669;
+ static volatile Object s670, s671, s672, s673, s674, s675, s676, s677, s678, s679;
+ static volatile Object s680, s681, s682, s683, s684, s685, s686, s687, s688, s689;
+ static volatile Object s690, s691, s692, s693, s694, s695, s696, s697, s698, s699;
+
+ static volatile Object s700, s701, s702, s703, s704, s705, s706, s707, s708, s709;
+ static volatile Object s710, s711, s712, s713, s714, s715, s716, s717, s718, s719;
+ static volatile Object s720, s721, s722, s723, s724, s725, s726, s727, s728, s729;
+ static volatile Object s730, s731, s732, s733, s734, s735, s736, s737, s738, s739;
+ static volatile Object s740, s741, s742, s743, s744, s745, s746, s747, s748, s749;
+ static volatile Object s750, s751, s752, s753, s754, s755, s756, s757, s758, s759;
+ static volatile Object s760, s761, s762, s763, s764, s765, s766, s767, s768, s769;
+ static volatile Object s770, s771, s772, s773, s774, s775, s776, s777, s778, s779;
+ static volatile Object s780, s781, s782, s783, s784, s785, s786, s787, s788, s789;
+ static volatile Object s790, s791, s792, s793, s794, s795, s796, s797, s798, s799;
+
+ static volatile Object s800, s801, s802, s803, s804, s805, s806, s807, s808, s809;
+ static volatile Object s810, s811, s812, s813, s814, s815, s816, s817, s818, s819;
+ static volatile Object s820, s821, s822, s823, s824, s825, s826, s827, s828, s829;
+ static volatile Object s830, s831, s832, s833, s834, s835, s836, s837, s838, s839;
+ static volatile Object s840, s841, s842, s843, s844, s845, s846, s847, s848, s849;
+ static volatile Object s850, s851, s852, s853, s854, s855, s856, s857, s858, s859;
+ static volatile Object s860, s861, s862, s863, s864, s865, s866, s867, s868, s869;
+ static volatile Object s870, s871, s872, s873, s874, s875, s876, s877, s878, s879;
+ static volatile Object s880, s881, s882, s883, s884, s885, s886, s887, s888, s889;
+ static volatile Object s890, s891, s892, s893, s894, s895, s896, s897, s898, s899;
+
+ static volatile Object s900, s901, s902, s903, s904, s905, s906, s907, s908, s909;
+ static volatile Object s910, s911, s912, s913, s914, s915, s916, s917, s918, s919;
+ static volatile Object s920, s921, s922, s923, s924, s925, s926, s927, s928, s929;
+ static volatile Object s930, s931, s932, s933, s934, s935, s936, s937, s938, s939;
+ static volatile Object s940, s941, s942, s943, s944, s945, s946, s947, s948, s949;
+ static volatile Object s950, s951, s952, s953, s954, s955, s956, s957, s958, s959;
+ static volatile Object s960, s961, s962, s963, s964, s965, s966, s967, s968, s969;
+ static volatile Object s970, s971, s972, s973, s974, s975, s976, s977, s978, s979;
+ static volatile Object s980, s981, s982, s983, s984, s985, s986, s987, s988, s989;
+ static volatile Object s990, s991, s992, s993, s994, s995, s996, s997, s998, s999;
+
+
+ volatile Object i0000, i0001, i0002, i0003, i0004, i0005, i0006, i0007, i0008, i0009;
+ volatile Object i0010, i0011, i0012, i0013, i0014, i0015, i0016, i0017, i0018, i0019;
+ volatile Object i0020, i0021, i0022, i0023, i0024, i0025, i0026, i0027, i0028, i0029;
+ volatile Object i0030, i0031, i0032, i0033, i0034, i0035, i0036, i0037, i0038, i0039;
+ volatile Object i0040, i0041, i0042, i0043, i0044, i0045, i0046, i0047, i0048, i0049;
+ volatile Object i0050, i0051, i0052, i0053, i0054, i0055, i0056, i0057, i0058, i0059;
+ volatile Object i0060, i0061, i0062, i0063, i0064, i0065, i0066, i0067, i0068, i0069;
+ volatile Object i0070, i0071, i0072, i0073, i0074, i0075, i0076, i0077, i0078, i0079;
+ volatile Object i0080, i0081, i0082, i0083, i0084, i0085, i0086, i0087, i0088, i0089;
+ volatile Object i0090, i0091, i0092, i0093, i0094, i0095, i0096, i0097, i0098, i0099;
+
+ volatile Object i0100, i0101, i0102, i0103, i0104, i0105, i0106, i0107, i0108, i0109;
+ volatile Object i0110, i0111, i0112, i0113, i0114, i0115, i0116, i0117, i0118, i0119;
+ volatile Object i0120, i0121, i0122, i0123, i0124, i0125, i0126, i0127, i0128, i0129;
+ volatile Object i0130, i0131, i0132, i0133, i0134, i0135, i0136, i0137, i0138, i0139;
+ volatile Object i0140, i0141, i0142, i0143, i0144, i0145, i0146, i0147, i0148, i0149;
+ volatile Object i0150, i0151, i0152, i0153, i0154, i0155, i0156, i0157, i0158, i0159;
+ volatile Object i0160, i0161, i0162, i0163, i0164, i0165, i0166, i0167, i0168, i0169;
+ volatile Object i0170, i0171, i0172, i0173, i0174, i0175, i0176, i0177, i0178, i0179;
+ volatile Object i0180, i0181, i0182, i0183, i0184, i0185, i0186, i0187, i0188, i0189;
+ volatile Object i0190, i0191, i0192, i0193, i0194, i0195, i0196, i0197, i0198, i0199;
+
+ volatile Object i0200, i0201, i0202, i0203, i0204, i0205, i0206, i0207, i0208, i0209;
+ volatile Object i0210, i0211, i0212, i0213, i0214, i0215, i0216, i0217, i0218, i0219;
+ volatile Object i0220, i0221, i0222, i0223, i0224, i0225, i0226, i0227, i0228, i0229;
+ volatile Object i0230, i0231, i0232, i0233, i0234, i0235, i0236, i0237, i0238, i0239;
+ volatile Object i0240, i0241, i0242, i0243, i0244, i0245, i0246, i0247, i0248, i0249;
+ volatile Object i0250, i0251, i0252, i0253, i0254, i0255, i0256, i0257, i0258, i0259;
+ volatile Object i0260, i0261, i0262, i0263, i0264, i0265, i0266, i0267, i0268, i0269;
+ volatile Object i0270, i0271, i0272, i0273, i0274, i0275, i0276, i0277, i0278, i0279;
+ volatile Object i0280, i0281, i0282, i0283, i0284, i0285, i0286, i0287, i0288, i0289;
+ volatile Object i0290, i0291, i0292, i0293, i0294, i0295, i0296, i0297, i0298, i0299;
+
+ volatile Object i0300, i0301, i0302, i0303, i0304, i0305, i0306, i0307, i0308, i0309;
+ volatile Object i0310, i0311, i0312, i0313, i0314, i0315, i0316, i0317, i0318, i0319;
+ volatile Object i0320, i0321, i0322, i0323, i0324, i0325, i0326, i0327, i0328, i0329;
+ volatile Object i0330, i0331, i0332, i0333, i0334, i0335, i0336, i0337, i0338, i0339;
+ volatile Object i0340, i0341, i0342, i0343, i0344, i0345, i0346, i0347, i0348, i0349;
+ volatile Object i0350, i0351, i0352, i0353, i0354, i0355, i0356, i0357, i0358, i0359;
+ volatile Object i0360, i0361, i0362, i0363, i0364, i0365, i0366, i0367, i0368, i0369;
+ volatile Object i0370, i0371, i0372, i0373, i0374, i0375, i0376, i0377, i0378, i0379;
+ volatile Object i0380, i0381, i0382, i0383, i0384, i0385, i0386, i0387, i0388, i0389;
+ volatile Object i0390, i0391, i0392, i0393, i0394, i0395, i0396, i0397, i0398, i0399;
+
+ volatile Object i0400, i0401, i0402, i0403, i0404, i0405, i0406, i0407, i0408, i0409;
+ volatile Object i0410, i0411, i0412, i0413, i0414, i0415, i0416, i0417, i0418, i0419;
+ volatile Object i0420, i0421, i0422, i0423, i0424, i0425, i0426, i0427, i0428, i0429;
+ volatile Object i0430, i0431, i0432, i0433, i0434, i0435, i0436, i0437, i0438, i0439;
+ volatile Object i0440, i0441, i0442, i0443, i0444, i0445, i0446, i0447, i0448, i0449;
+ volatile Object i0450, i0451, i0452, i0453, i0454, i0455, i0456, i0457, i0458, i0459;
+ volatile Object i0460, i0461, i0462, i0463, i0464, i0465, i0466, i0467, i0468, i0469;
+ volatile Object i0470, i0471, i0472, i0473, i0474, i0475, i0476, i0477, i0478, i0479;
+ volatile Object i0480, i0481, i0482, i0483, i0484, i0485, i0486, i0487, i0488, i0489;
+ volatile Object i0490, i0491, i0492, i0493, i0494, i0495, i0496, i0497, i0498, i0499;
+
+ volatile Object i0500, i0501, i0502, i0503, i0504, i0505, i0506, i0507, i0508, i0509;
+ volatile Object i0510, i0511, i0512, i0513, i0514, i0515, i0516, i0517, i0518, i0519;
+ volatile Object i0520, i0521, i0522, i0523, i0524, i0525, i0526, i0527, i0528, i0529;
+ volatile Object i0530, i0531, i0532, i0533, i0534, i0535, i0536, i0537, i0538, i0539;
+ volatile Object i0540, i0541, i0542, i0543, i0544, i0545, i0546, i0547, i0548, i0549;
+ volatile Object i0550, i0551, i0552, i0553, i0554, i0555, i0556, i0557, i0558, i0559;
+ volatile Object i0560, i0561, i0562, i0563, i0564, i0565, i0566, i0567, i0568, i0569;
+ volatile Object i0570, i0571, i0572, i0573, i0574, i0575, i0576, i0577, i0578, i0579;
+ volatile Object i0580, i0581, i0582, i0583, i0584, i0585, i0586, i0587, i0588, i0589;
+ volatile Object i0590, i0591, i0592, i0593, i0594, i0595, i0596, i0597, i0598, i0599;
+
+ volatile Object i0600, i0601, i0602, i0603, i0604, i0605, i0606, i0607, i0608, i0609;
+ volatile Object i0610, i0611, i0612, i0613, i0614, i0615, i0616, i0617, i0618, i0619;
+ volatile Object i0620, i0621, i0622, i0623, i0624, i0625, i0626, i0627, i0628, i0629;
+ volatile Object i0630, i0631, i0632, i0633, i0634, i0635, i0636, i0637, i0638, i0639;
+ volatile Object i0640, i0641, i0642, i0643, i0644, i0645, i0646, i0647, i0648, i0649;
+ volatile Object i0650, i0651, i0652, i0653, i0654, i0655, i0656, i0657, i0658, i0659;
+ volatile Object i0660, i0661, i0662, i0663, i0664, i0665, i0666, i0667, i0668, i0669;
+ volatile Object i0670, i0671, i0672, i0673, i0674, i0675, i0676, i0677, i0678, i0679;
+ volatile Object i0680, i0681, i0682, i0683, i0684, i0685, i0686, i0687, i0688, i0689;
+ volatile Object i0690, i0691, i0692, i0693, i0694, i0695, i0696, i0697, i0698, i0699;
+
+ volatile Object i0700, i0701, i0702, i0703, i0704, i0705, i0706, i0707, i0708, i0709;
+ volatile Object i0710, i0711, i0712, i0713, i0714, i0715, i0716, i0717, i0718, i0719;
+ volatile Object i0720, i0721, i0722, i0723, i0724, i0725, i0726, i0727, i0728, i0729;
+ volatile Object i0730, i0731, i0732, i0733, i0734, i0735, i0736, i0737, i0738, i0739;
+ volatile Object i0740, i0741, i0742, i0743, i0744, i0745, i0746, i0747, i0748, i0749;
+ volatile Object i0750, i0751, i0752, i0753, i0754, i0755, i0756, i0757, i0758, i0759;
+ volatile Object i0760, i0761, i0762, i0763, i0764, i0765, i0766, i0767, i0768, i0769;
+ volatile Object i0770, i0771, i0772, i0773, i0774, i0775, i0776, i0777, i0778, i0779;
+ volatile Object i0780, i0781, i0782, i0783, i0784, i0785, i0786, i0787, i0788, i0789;
+ volatile Object i0790, i0791, i0792, i0793, i0794, i0795, i0796, i0797, i0798, i0799;
+
+ volatile Object i0800, i0801, i0802, i0803, i0804, i0805, i0806, i0807, i0808, i0809;
+ volatile Object i0810, i0811, i0812, i0813, i0814, i0815, i0816, i0817, i0818, i0819;
+ volatile Object i0820, i0821, i0822, i0823, i0824, i0825, i0826, i0827, i0828, i0829;
+ volatile Object i0830, i0831, i0832, i0833, i0834, i0835, i0836, i0837, i0838, i0839;
+ volatile Object i0840, i0841, i0842, i0843, i0844, i0845, i0846, i0847, i0848, i0849;
+ volatile Object i0850, i0851, i0852, i0853, i0854, i0855, i0856, i0857, i0858, i0859;
+ volatile Object i0860, i0861, i0862, i0863, i0864, i0865, i0866, i0867, i0868, i0869;
+ volatile Object i0870, i0871, i0872, i0873, i0874, i0875, i0876, i0877, i0878, i0879;
+ volatile Object i0880, i0881, i0882, i0883, i0884, i0885, i0886, i0887, i0888, i0889;
+ volatile Object i0890, i0891, i0892, i0893, i0894, i0895, i0896, i0897, i0898, i0899;
+
+ volatile Object i0900, i0901, i0902, i0903, i0904, i0905, i0906, i0907, i0908, i0909;
+ volatile Object i0910, i0911, i0912, i0913, i0914, i0915, i0916, i0917, i0918, i0919;
+ volatile Object i0920, i0921, i0922, i0923, i0924, i0925, i0926, i0927, i0928, i0929;
+ volatile Object i0930, i0931, i0932, i0933, i0934, i0935, i0936, i0937, i0938, i0939;
+ volatile Object i0940, i0941, i0942, i0943, i0944, i0945, i0946, i0947, i0948, i0949;
+ volatile Object i0950, i0951, i0952, i0953, i0954, i0955, i0956, i0957, i0958, i0959;
+ volatile Object i0960, i0961, i0962, i0963, i0964, i0965, i0966, i0967, i0968, i0969;
+ volatile Object i0970, i0971, i0972, i0973, i0974, i0975, i0976, i0977, i0978, i0979;
+ volatile Object i0980, i0981, i0982, i0983, i0984, i0985, i0986, i0987, i0988, i0989;
+ volatile Object i0990, i0991, i0992, i0993, i0994, i0995, i0996, i0997, i0998, i0999;
+
+ volatile Object i1000, i1001, i1002, i1003, i1004, i1005, i1006, i1007, i1008, i1009;
+ volatile Object i1010, i1011, i1012, i1013, i1014, i1015, i1016, i1017, i1018, i1019;
+ volatile Object i1020, i1021, i1022, i1023, i1024, i1025, i1026, i1027, i1028, i1029;
+ volatile Object i1030, i1031, i1032, i1033, i1034, i1035, i1036, i1037, i1038, i1039;
+ volatile Object i1040, i1041, i1042, i1043, i1044, i1045, i1046, i1047, i1048, i1049;
+ volatile Object i1050, i1051, i1052, i1053, i1054, i1055, i1056, i1057, i1058, i1059;
+ volatile Object i1060, i1061, i1062, i1063, i1064, i1065, i1066, i1067, i1068, i1069;
+ volatile Object i1070, i1071, i1072, i1073, i1074, i1075, i1076, i1077, i1078, i1079;
+ volatile Object i1080, i1081, i1082, i1083, i1084, i1085, i1086, i1087, i1088, i1089;
+ volatile Object i1090, i1091, i1092, i1093, i1094, i1095, i1096, i1097, i1098, i1099;
+
+
+ // Note: ARM64, registers X16 and X17 are respectively IP0 and IP1,
+ // the scratch registers used by the VIXL AArch64 assembler (and to
+ // some extent, by ART's ARM64 code generator).
+
+ /// CHECK-START-ARM64: void Main.testStaticVolatileFieldGetWithLargeOffset() disassembly (after)
+ /// CHECK: StaticFieldGet
+ /// CHECK: mov x17, #<<Offset:0x[0-9a-f]{4}>>
+ /// CHECK: add x16, {{x\d+}}, x17
+ /// CHECK: ldar {{w\d+}}, [x16]
+ static void testStaticVolatileFieldGetWithLargeOffset() {
+ // The offset of this static field cannot be encoded as an immediate on ARM64.
+ Object s = s999;
+ }
+
+ /// CHECK-START-ARM64: void Main.testInstanceVolatileFieldGetWithLargeOffset() disassembly (after)
+ /// CHECK: InstanceFieldGet
+ /// CHECK: mov x17, #<<Offset:0x[0-9a-f]{4}>>
+ /// CHECK: add x16, {{x\d+}}, x17
+ /// CHECK: ldar {{w\d+}}, [x16]
+ void testInstanceVolatileFieldGetWithLargeOffset() {
+ // The offset of this instance field cannot be encoded as an immediate on ARM64.
+ Object i = i1029;
+ }
+
+
+ public static void main(String[] args) {
+ testStaticVolatileFieldGetWithLargeOffset();
+ Main m = new Main();
+ m.testInstanceVolatileFieldGetWithLargeOffset();
+ System.out.println("passed");
+ }
+
+}
diff --git a/test/636-wrong-static-access/expected.txt b/test/636-wrong-static-access/expected.txt
new file mode 100644
index 0000000000..6a5618ebc6
--- /dev/null
+++ b/test/636-wrong-static-access/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/636-wrong-static-access/info.txt b/test/636-wrong-static-access/info.txt
new file mode 100644
index 0000000000..184d858cb9
--- /dev/null
+++ b/test/636-wrong-static-access/info.txt
@@ -0,0 +1,2 @@
+Test that the compiler checks if a resolved field is
+of the expected static/instance kind.
diff --git a/test/636-wrong-static-access/run b/test/636-wrong-static-access/run
new file mode 100755
index 0000000000..5e999209b8
--- /dev/null
+++ b/test/636-wrong-static-access/run
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 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.
+
+# Make verification soft fail, to ensure the verifier does not flag
+# the method we want to compile as "non-compilable" because it sees
+# the method will throw IncompatibleClassChangeError.
+exec ${RUN} $@ --verify-soft-fail
diff --git a/test/636-wrong-static-access/src-ex/Foo.java b/test/636-wrong-static-access/src-ex/Foo.java
new file mode 100644
index 0000000000..9e3b7a74c8
--- /dev/null
+++ b/test/636-wrong-static-access/src-ex/Foo.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+public class Foo {
+ public static void doTest() {
+ // Execute foo once to make sure the dex cache will be updated.
+ try {
+ foo();
+ throw new Error("Expected IncompatibleClassChangeError");
+ } catch (IncompatibleClassChangeError e) {
+ // Expected.
+ }
+ Main.ensureJitCompiled(Foo.class, "foo");
+ try {
+ foo();
+ throw new Error("Expected IncompatibleClassChangeError");
+ } catch (IncompatibleClassChangeError e) {
+ // Expected.
+ }
+ }
+
+ public static void foo() {
+ System.out.println(Holder.field);
+ }
+}
diff --git a/test/636-wrong-static-access/src/Holder.java b/test/636-wrong-static-access/src/Holder.java
new file mode 100644
index 0000000000..f3b1c5717c
--- /dev/null
+++ b/test/636-wrong-static-access/src/Holder.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+public class Holder {
+ public static int field = 42;
+}
diff --git a/test/636-wrong-static-access/src/Main.java b/test/636-wrong-static-access/src/Main.java
new file mode 100644
index 0000000000..bd8548e372
--- /dev/null
+++ b/test/636-wrong-static-access/src/Main.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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;
+
+public class Main {
+ static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/636-wrong-static-access-ex.jar";
+
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ 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<?> foo = loader.loadClass("Foo");
+ Method doTest = foo.getDeclaredMethod("doTest");
+ doTest.invoke(null);
+ }
+
+ public static native void ensureJitCompiled(Class<?> cls, String methodName);
+}
diff --git a/test/636-wrong-static-access/src2/Holder.java b/test/636-wrong-static-access/src2/Holder.java
new file mode 100644
index 0000000000..a26da24319
--- /dev/null
+++ b/test/636-wrong-static-access/src2/Holder.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+public class Holder {
+ public int field = 42;
+}
diff --git a/test/706-checker-scheduler/expected.txt b/test/706-checker-scheduler/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/706-checker-scheduler/expected.txt
diff --git a/test/706-checker-scheduler/info.txt b/test/706-checker-scheduler/info.txt
new file mode 100644
index 0000000000..b4ad9b4378
--- /dev/null
+++ b/test/706-checker-scheduler/info.txt
@@ -0,0 +1 @@
+Tests for HInstruction scheduler.
diff --git a/test/706-checker-scheduler/src/Main.java b/test/706-checker-scheduler/src/Main.java
new file mode 100644
index 0000000000..1721e4294e
--- /dev/null
+++ b/test/706-checker-scheduler/src/Main.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+public class Main {
+
+ static int static_variable = 0;
+
+ /// CHECK-START-ARM64: int Main.arrayAccess() scheduler (before)
+ /// CHECK: <<Const1:i\d+>> IntConstant 1
+ /// CHECK: <<i0:i\d+>> Phi
+ /// CHECK: <<res0:i\d+>> Phi
+ /// CHECK: <<Array:i\d+>> IntermediateAddress
+ /// CHECK: <<ArrayGet1:i\d+>> ArrayGet [<<Array>>,<<i0>>]
+ /// CHECK: <<res1:i\d+>> Add [<<res0>>,<<ArrayGet1>>]
+ /// CHECK: <<i1:i\d+>> Add [<<i0>>,<<Const1>>]
+ /// CHECK: <<ArrayGet2:i\d+>> ArrayGet [<<Array>>,<<i1>>]
+ /// CHECK: Add [<<res1>>,<<ArrayGet2>>]
+
+ /// CHECK-START-ARM64: int Main.arrayAccess() scheduler (after)
+ /// CHECK: <<Const1:i\d+>> IntConstant 1
+ /// CHECK: <<i0:i\d+>> Phi
+ /// CHECK: <<res0:i\d+>> Phi
+ /// CHECK: <<Array:i\d+>> IntermediateAddress
+ /// CHECK: <<ArrayGet1:i\d+>> ArrayGet [<<Array>>,<<i0>>]
+ /// CHECK: <<i1:i\d+>> Add [<<i0>>,<<Const1>>]
+ /// CHECK: <<ArrayGet2:i\d+>> ArrayGet [<<Array>>,<<i1>>]
+ /// CHECK: <<res1:i\d+>> Add [<<res0>>,<<ArrayGet1>>]
+ /// CHECK: Add [<<res1>>,<<ArrayGet2>>]
+
+ public static int arrayAccess() {
+ int res = 0;
+ int [] array = new int[10];
+ for (int i = 0; i < 9; i++) {
+ res += array[i];
+ res += array[i + 1];
+ }
+ return res;
+ }
+
+ /// CHECK-START-ARM64: int Main.intDiv(int) scheduler (before)
+ /// CHECK: Sub
+ /// CHECK: DivZeroCheck
+ /// CHECK: Div
+ /// CHECK: StaticFieldSet
+
+ /// CHECK-START-ARM64: int Main.intDiv(int) scheduler (after)
+ /// CHECK: Sub
+ /// CHECK-NOT: StaticFieldSet
+ /// CHECK: DivZeroCheck
+ /// CHECK-NOT: Sub
+ /// CHECK: Div
+ public static int intDiv(int arg) {
+ int res = 0;
+ int tmp = arg;
+ for (int i = 1; i < arg; i++) {
+ tmp -= i;
+ res = res / i; // div-zero check barrier.
+ static_variable++;
+ }
+ res += tmp;
+ return res;
+ }
+
+ public static void main(String[] args) {
+ if ((arrayAccess() + intDiv(10)) != -35) {
+ System.out.println("FAIL");
+ }
+ }
+}
diff --git a/test/900-hello-plugin/run b/test/900-hello-plugin/run
index 35b08715a1..50835f89af 100755
--- a/test/900-hello-plugin/run
+++ b/test/900-hello-plugin/run
@@ -18,7 +18,5 @@ plugin=libartagentd.so
if [[ "$@" == *"-O"* ]]; then
plugin=libartagent.so
fi
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --runtime-option -agentpath:${plugin}=test_900 \
+./default-run "$@" --runtime-option -agentpath:${plugin}=test_900 \
--android-runtime-option -Xplugin:${plugin}
diff --git a/test/901-hello-ti-agent/run b/test/901-hello-ti-agent/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/901-hello-ti-agent/run
+++ b/test/901-hello-ti-agent/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/902-hello-transformation/run b/test/902-hello-transformation/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/902-hello-transformation/run
+++ b/test/902-hello-transformation/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/903-hello-tagging/run b/test/903-hello-tagging/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/903-hello-tagging/run
+++ b/test/903-hello-tagging/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/904-object-allocation/run b/test/904-object-allocation/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/904-object-allocation/run
+++ b/test/904-object-allocation/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/905-object-free/run b/test/905-object-free/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/905-object-free/run
+++ b/test/905-object-free/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/906-iterate-heap/run b/test/906-iterate-heap/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/906-iterate-heap/run
+++ b/test/906-iterate-heap/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/907-get-loaded-classes/run b/test/907-get-loaded-classes/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/907-get-loaded-classes/run
+++ b/test/907-get-loaded-classes/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/908-gc-start-finish/gc_callbacks.cc b/test/908-gc-start-finish/gc_callbacks.cc
index 59801ff648..8f96ee63ef 100644
--- a/test/908-gc-start-finish/gc_callbacks.cc
+++ b/test/908-gc-start-finish/gc_callbacks.cc
@@ -38,43 +38,32 @@ static void JNICALL GarbageCollectionStart(jvmtiEnv* ti_env ATTRIBUTE_UNUSED) {
}
extern "C" JNIEXPORT void JNICALL Java_Main_setupGcCallback(
- JNIEnv* env ATTRIBUTE_UNUSED, jclass klass ATTRIBUTE_UNUSED) {
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
callbacks.GarbageCollectionFinish = GarbageCollectionFinish;
callbacks.GarbageCollectionStart = GarbageCollectionStart;
jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
- if (ret != JVMTI_ERROR_NONE) {
- char* err;
- jvmti_env->GetErrorName(ret, &err);
- printf("Error setting callbacks: %s\n", err);
- jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
- }
+ JvmtiErrorToException(env, ret);
}
-extern "C" JNIEXPORT void JNICALL Java_Main_enableGcTracking(JNIEnv* env ATTRIBUTE_UNUSED,
+extern "C" JNIEXPORT void JNICALL Java_Main_enableGcTracking(JNIEnv* env,
jclass klass ATTRIBUTE_UNUSED,
jboolean enable) {
jvmtiError ret = jvmti_env->SetEventNotificationMode(
enable ? JVMTI_ENABLE : JVMTI_DISABLE,
JVMTI_EVENT_GARBAGE_COLLECTION_START,
nullptr);
- if (ret != JVMTI_ERROR_NONE) {
- char* err;
- jvmti_env->GetErrorName(ret, &err);
- printf("Error enabling/disabling gc callbacks: %s\n", err);
- jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ if (JvmtiErrorToException(env, ret)) {
+ return;
}
ret = jvmti_env->SetEventNotificationMode(
enable ? JVMTI_ENABLE : JVMTI_DISABLE,
JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,
nullptr);
- if (ret != JVMTI_ERROR_NONE) {
- char* err;
- jvmti_env->GetErrorName(ret, &err);
- printf("Error enabling/disabling gc callbacks: %s\n", err);
- jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ if (JvmtiErrorToException(env, ret)) {
+ return;
}
}
diff --git a/test/908-gc-start-finish/run b/test/908-gc-start-finish/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/908-gc-start-finish/run
+++ b/test/908-gc-start-finish/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/909-attach-agent/run b/test/909-attach-agent/run
index 985341bd4f..4a2eb34a1d 100755
--- a/test/909-attach-agent/run
+++ b/test/909-attach-agent/run
@@ -21,17 +21,13 @@ if [[ "$@" == *"-O"* ]]; then
plugin=libopenjdkjvmti.so
fi
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --android-runtime-option -Xplugin:${plugin} \
- --android-runtime-option -Xfully-deoptable \
+./default-run "$@" --android-runtime-option -Xplugin:${plugin} \
+ --android-runtime-option -Xcompiler-option \
+ --android-runtime-option --debuggable \
--args agent:${agent}=909-attach-agent
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --android-runtime-option -Xfully-deoptable \
+./default-run "$@" --android-runtime-option -Xcompiler-option \
+ --android-runtime-option --debuggable \
--args agent:${agent}=909-attach-agent
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --args agent:${agent}=909-attach-agent
+./default-run "$@" --args agent:${agent}=909-attach-agent
diff --git a/test/909-attach-agent/src/Main.java b/test/909-attach-agent/src/Main.java
index 8a8a087458..569b89ad7d 100644
--- a/test/909-attach-agent/src/Main.java
+++ b/test/909-attach-agent/src/Main.java
@@ -19,7 +19,7 @@ import java.io.IOException;
public class Main {
public static void main(String[] args) {
- System.out.println("Hello, world!");
+ System.err.println("Hello, world!");
for(String a : args) {
if(a.startsWith("agent:")) {
String agent = a.substring(6);
@@ -30,6 +30,6 @@ public class Main {
}
}
}
- System.out.println("Goodbye!");
+ System.err.println("Goodbye!");
}
}
diff --git a/test/910-methods/run b/test/910-methods/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/910-methods/run
+++ b/test/910-methods/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/911-get-stack-trace/run b/test/911-get-stack-trace/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/911-get-stack-trace/run
+++ b/test/911-get-stack-trace/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/911-get-stack-trace/src/PrintThread.java b/test/911-get-stack-trace/src/PrintThread.java
index 97815ccad9..136fd80d40 100644
--- a/test/911-get-stack-trace/src/PrintThread.java
+++ b/test/911-get-stack-trace/src/PrintThread.java
@@ -44,6 +44,9 @@ public class PrintThread {
if (name.contains("Daemon")) {
// Do not print daemon stacks, as they're non-deterministic.
stackSerialization = "<not printed>";
+ } else if (name.startsWith("Jit thread pool worker")) {
+ // Skip JIT thread pool. It may or may not be there depending on configuration.
+ continue;
} else {
StringBuilder sb = new StringBuilder();
for (String[] stackElement : (String[][])stackInfo[1]) {
diff --git a/test/912-classes/expected.txt b/test/912-classes/expected.txt
index d0b77a4bae..328216b324 100644
--- a/test/912-classes/expected.txt
+++ b/test/912-classes/expected.txt
@@ -29,7 +29,7 @@ int 100000
class [Ljava.lang.String; 10000
class java.lang.Object 111
class Main$TestForNonInit 11
-class Main$TestForInitFail 1001
+class Main$TestForInitFail 1011
int []
class [Ljava.lang.String; []
class java.lang.Object []
diff --git a/test/912-classes/run b/test/912-classes/run
index 20dfc4b767..f24db40cb0 100755
--- a/test/912-classes/run
+++ b/test/912-classes/run
@@ -18,7 +18,5 @@
# In certain configurations, the app images may be valid even in a new classloader. Turn off
# app images to avoid the issue.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti \
+./default-run "$@" --jvmti \
--no-app-image
diff --git a/test/913-heaps/run b/test/913-heaps/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/913-heaps/run
+++ b/test/913-heaps/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/914-hello-obsolescence/run b/test/914-hello-obsolescence/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/914-hello-obsolescence/run
+++ b/test/914-hello-obsolescence/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/915-obsolete-2/run b/test/915-obsolete-2/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/915-obsolete-2/run
+++ b/test/915-obsolete-2/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/916-obsolete-jit/run b/test/916-obsolete-jit/run
index 9056211284..b6d406fd99 100755
--- a/test/916-obsolete-jit/run
+++ b/test/916-obsolete-jit/run
@@ -21,7 +21,5 @@ if [[ "$@" == *"--jit"* ]]; then
else
other_args="--jit"
fi
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- ${other_args} \
+./default-run "$@" ${other_args} \
--jvmti
diff --git a/test/916-obsolete-jit/src/Main.java b/test/916-obsolete-jit/src/Main.java
index 1b03200ba5..2b3296f1f2 100644
--- a/test/916-obsolete-jit/src/Main.java
+++ b/test/916-obsolete-jit/src/Main.java
@@ -116,37 +116,27 @@ public class Main {
doTest(new Transform(), new TestWatcher());
}
- // TODO Workaround to (1) inability to ensure that current_method is not put into a register by
- // the JIT and/or (2) inability to deoptimize frames near runtime functions.
- // TODO Fix one/both of these issues.
- public static void doCall(Runnable r) {
- r.run();
- }
-
private static boolean interpreting = true;
private static boolean retry = false;
public static void doTest(Transform t, TestWatcher w) {
// Get the methods that need to be optimized.
Method say_hi_method;
- Method do_call_method;
// Figure out if we can even JIT at all.
final boolean has_jit = hasJit();
try {
say_hi_method = Transform.class.getDeclaredMethod(
"sayHi", Runnable.class, Consumer.class);
- do_call_method = Main.class.getDeclaredMethod("doCall", Runnable.class);
} catch (Exception e) {
System.out.println("Unable to find methods!");
e.printStackTrace();
return;
}
// Makes sure the stack is the way we want it for the test and does the redefinition. It will
- // set the retry boolean to true if we need to go around again due to a bad stack.
+ // set the retry boolean to true if the stack does not have a JIT-compiled sayHi entry. This can
+ // only happen if the method gets GC'd.
Runnable do_redefinition = () -> {
- if (has_jit &&
- (Main.isInterpretedFunction(say_hi_method, true) ||
- Main.isInterpretedFunction(do_call_method, false))) {
+ if (has_jit && Main.isInterpretedFunction(say_hi_method, true)) {
// Try again. We are not running the right jitted methods/cannot redefine them now.
retry = true;
} else {
@@ -161,7 +151,6 @@ public class Main {
do {
// Run ensureJitCompiled here since it might get GCd
ensureJitCompiled(Transform.class, "sayHi");
- ensureJitCompiled(Main.class, "doCall");
// Clear output.
w.clear();
// Try and redefine.
diff --git a/test/916-obsolete-jit/src/Transform.java b/test/916-obsolete-jit/src/Transform.java
index f4dcf09dc6..9c9adbc22d 100644
--- a/test/916-obsolete-jit/src/Transform.java
+++ b/test/916-obsolete-jit/src/Transform.java
@@ -29,13 +29,7 @@ class Transform {
reporter.accept("Pre Start private method call");
Start(reporter);
reporter.accept("Post Start private method call");
- // TODO Revisit with b/33616143
- // TODO Uncomment this once either b/33630159 or b/33616143 are resolved.
- // r.run();
- // TODO This doCall function is a very temporary fix until we get either deoptimization near
- // runtime frames working, forcing current method to be always read from the stack or both
- // working.
- Main.doCall(r);
+ r.run();
reporter.accept("Pre Finish private method call");
Finish(reporter);
reporter.accept("Post Finish private method call");
diff --git a/test/917-fields-transformation/run b/test/917-fields-transformation/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/917-fields-transformation/run
+++ b/test/917-fields-transformation/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/918-fields/run b/test/918-fields/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/918-fields/run
+++ b/test/918-fields/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/919-obsolete-fields/run b/test/919-obsolete-fields/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/919-obsolete-fields/run
+++ b/test/919-obsolete-fields/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/919-obsolete-fields/src/Main.java b/test/919-obsolete-fields/src/Main.java
index 1d893f125a..ffb9897236 100644
--- a/test/919-obsolete-fields/src/Main.java
+++ b/test/919-obsolete-fields/src/Main.java
@@ -120,13 +120,6 @@ public class Main {
doTest(new Transform(w), w);
}
- // TODO Workaround to (1) inability to ensure that current_method is not put into a register by
- // the JIT and/or (2) inability to deoptimize frames near runtime functions.
- // TODO Fix one/both of these issues.
- public static void doCall(Runnable r) {
- r.run();
- }
-
private static boolean interpreting = true;
private static boolean retry = false;
diff --git a/test/919-obsolete-fields/src/Transform.java b/test/919-obsolete-fields/src/Transform.java
index abd1d19b66..c8e3cbd934 100644
--- a/test/919-obsolete-fields/src/Transform.java
+++ b/test/919-obsolete-fields/src/Transform.java
@@ -34,12 +34,7 @@ class Transform {
reporter.accept("Pre Start private method call");
Start();
reporter.accept("Post Start private method call");
- // TODO Revist with b/33616143
- // TODO Uncomment this
- // r.run();
- // TODO This is a very temporary fix until we get either deoptimization near runtime frames
- // working, forcing current method to be always read from the stack or both working.
- Main.doCall(r);
+ r.run();
reporter.accept("Pre Finish private method call");
Finish();
reporter.accept("Post Finish private method call");
diff --git a/test/920-objects/run b/test/920-objects/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/920-objects/run
+++ b/test/920-objects/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/921-hello-failure/expected.txt b/test/921-hello-failure/expected.txt
index 9615e6b33d..e9b6a20cd6 100644
--- a/test/921-hello-failure/expected.txt
+++ b/test/921-hello-failure/expected.txt
@@ -29,3 +29,21 @@ hello2 - MultiRetrans
Transformation error : java.lang.Exception(Failed to retransform classes <LTransform;, LTransform2;> due to JVMTI_ERROR_NAMES_DONT_MATCH)
hello - MultiRetrans
hello2 - MultiRetrans
+hello - NewMethod
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED)
+hello - NewMethod
+hello2 - MissingMethod
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform3;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED)
+hello2 - MissingMethod
+hello - MethodChange
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED)
+hello - MethodChange
+hello - NewField
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED)
+hello - NewField
+hello there - MissingField
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform4;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED)
+hello there - MissingField
+hello there again - FieldChange
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform4;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED)
+hello there again - FieldChange
diff --git a/test/921-hello-failure/run b/test/921-hello-failure/run
index 3ef4832da2..8be0ed4aed 100755
--- a/test/921-hello-failure/run
+++ b/test/921-hello-failure/run
@@ -15,6 +15,4 @@
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/921-hello-failure/src/FieldChange.java b/test/921-hello-failure/src/FieldChange.java
new file mode 100644
index 0000000000..cc2ea284d9
--- /dev/null
+++ b/test/921-hello-failure/src/FieldChange.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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.util.Base64;
+
+class FieldChange {
+ // The following is a base64 encoding of the following class.
+ // class Transform4 {
+ // private Object greeting;
+ // public Transform4(String hi) { }
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFwoABgAQBwARCAASCgACABMHABQHABUBAAhncmVldGluZwEAEkxqYXZhL2xhbmcv" +
+ "T2JqZWN0OwEABjxpbml0PgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABENvZGUBAA9MaW5lTnVt" +
+ "YmVyVGFibGUBAAVzYXlIaQEAClNvdXJjZUZpbGUBAA9UcmFuc2Zvcm00LmphdmEMAAkAFgEAD2ph" +
+ "dmEvbGFuZy9FcnJvcgEAFVNob3VsZCBub3QgYmUgY2FsbGVkIQwACQAKAQAKVHJhbnNmb3JtNAEA" +
+ "EGphdmEvbGFuZy9PYmplY3QBAAMoKVYAIAAFAAYAAAABAAIABwAIAAAAAgABAAkACgABAAsAAAAd" +
+ "AAEAAgAAAAUqtwABsQAAAAEADAAAAAYAAQAAAAMAAQANAAoAAQALAAAAIgADAAIAAAAKuwACWRID" +
+ "twAEvwAAAAEADAAAAAYAAQAAAAUAAQAOAAAAAgAP");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQASXs5yszuhud+/w4q07495k9eO7Yb+l8u4AgAAcAAAAHhWNBIAAAAAAAAAABgCAAAM" +
+ "AAAAcAAAAAUAAACgAAAAAgAAALQAAAABAAAAzAAAAAQAAADUAAAAAQAAAPQAAACkAQAAFAEAAFYB" +
+ "AABeAQAAbAEAAH8BAACTAQAApwEAAL4BAADPAQAA0gEAANYBAADqAQAA9AEAAAEAAAACAAAAAwAA" +
+ "AAQAAAAHAAAABwAAAAQAAAAAAAAACAAAAAQAAABQAQAAAAACAAoAAAAAAAEAAAAAAAAAAQALAAAA" +
+ "AQABAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAAAcCAAAAAAAAAgACAAEAAAD7" +
+ "AQAABAAAAHAQAwAAAA4ABAACAAIAAAABAgAACQAAACIAAQAbAQUAAABwIAIAEAAnAAAAAQAAAAMA" +
+ "Bjxpbml0PgAMTFRyYW5zZm9ybTQ7ABFMamF2YS9sYW5nL0Vycm9yOwASTGphdmEvbGFuZy9PYmpl" +
+ "Y3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAFVNob3VsZCBub3QgYmUgY2FsbGVkIQAPVHJhbnNmb3Jt" +
+ "NC5qYXZhAAFWAAJWTAASZW1pdHRlcjogamFjay00LjIyAAhncmVldGluZwAFc2F5SGkAAwEABw4A" +
+ "BQEABw4AAAEBAQACAIGABJQCAQGsAgANAAAAAAAAAAEAAAAAAAAAAQAAAAwAAABwAAAAAgAAAAUA" +
+ "AACgAAAAAwAAAAIAAAC0AAAABAAAAAEAAADMAAAABQAAAAQAAADUAAAABgAAAAEAAAD0AAAAASAA" +
+ "AAIAAAAUAQAAARAAAAEAAABQAQAAAiAAAAwAAABWAQAAAyAAAAIAAAD7AQAAACAAAAEAAAAHAgAA" +
+ "ABAAAAEAAAAYAgAA");
+
+ public static void doTest(Transform4 t) {
+ t.sayHi("FieldChange");
+ try {
+ Main.doCommonClassRedefinition(Transform4.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("FieldChange");
+ }
+}
diff --git a/test/921-hello-failure/src/Main.java b/test/921-hello-failure/src/Main.java
index 67ca1e15d6..61d69e7396 100644
--- a/test/921-hello-failure/src/Main.java
+++ b/test/921-hello-failure/src/Main.java
@@ -25,6 +25,12 @@ public class Main {
ReorderInterface.doTest(new Transform2());
MultiRedef.doTest(new Transform(), new Transform2());
MultiRetrans.doTest(new Transform(), new Transform2());
+ NewMethod.doTest(new Transform());
+ MissingMethod.doTest(new Transform3());
+ MethodChange.doTest(new Transform());
+ NewField.doTest(new Transform());
+ MissingField.doTest(new Transform4("there"));
+ FieldChange.doTest(new Transform4("there again"));
}
// Transforms the class. This throws an exception if something goes wrong.
diff --git a/test/921-hello-failure/src/MethodChange.java b/test/921-hello-failure/src/MethodChange.java
new file mode 100644
index 0000000000..16f57788c8
--- /dev/null
+++ b/test/921-hello-failure/src/MethodChange.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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.util.Base64;
+
+class MethodChange {
+ // The following is a base64 encoding of the following class.
+ // class Transform {
+ // void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFQoABgAPBwAQCAARCgACABIHABMHABQBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP" +
+ "TGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3VyY2VG" +
+ "aWxlAQAOVHJhbnNmb3JtLmphdmEMAAcACAEAD2phdmEvbGFuZy9FcnJvcgEAFVNob3VsZCBub3Qg" +
+ "YmUgY2FsbGVkIQwABwAMAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAAgAAUABgAAAAAA" +
+ "AgAAAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAIAAAALAAwAAQAJAAAA" +
+ "IgADAAIAAAAKuwACWRIDtwAEvwAAAAEACgAAAAYAAQAAAAQAAQANAAAAAgAO");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQCrV81cy4Q+YKMMMqc0bZEO5Y1X5u7irPeQAgAAcAAAAHhWNBIAAAAAAAAAAPwBAAAL" +
+ "AAAAcAAAAAUAAACcAAAAAgAAALAAAAAAAAAAAAAAAAQAAADIAAAAAQAAAOgAAACIAQAACAEAAEoB" +
+ "AABSAQAAXwEAAHIBAACGAQAAmgEAALEBAADBAQAAxAEAAMgBAADcAQAAAQAAAAIAAAADAAAABAAA" +
+ "AAcAAAAHAAAABAAAAAAAAAAIAAAABAAAAEQBAAAAAAAAAAAAAAAAAQAKAAAAAQABAAAAAAACAAAA" +
+ "AAAAAAAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAAO4BAAAAAAAAAQABAAEAAADjAQAABAAAAHAQAwAA" +
+ "AA4ABAACAAIAAADoAQAACQAAACIAAQAbAQUAAABwIAIAEAAnAAAAAQAAAAMABjxpbml0PgALTFRy" +
+ "YW5zZm9ybTsAEUxqYXZhL2xhbmcvRXJyb3I7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xh" +
+ "bmcvU3RyaW5nOwAVU2hvdWxkIG5vdCBiZSBjYWxsZWQhAA5UcmFuc2Zvcm0uamF2YQABVgACVkwA" +
+ "EmVtaXR0ZXI6IGphY2stNC4yNAAFc2F5SGkAAgAHDgAEAQAHDgAAAAEBAICABIgCAQCgAgwAAAAA" +
+ "AAAAAQAAAAAAAAABAAAACwAAAHAAAAACAAAABQAAAJwAAAADAAAAAgAAALAAAAAFAAAABAAAAMgA" +
+ "AAAGAAAAAQAAAOgAAAABIAAAAgAAAAgBAAABEAAAAQAAAEQBAAACIAAACwAAAEoBAAADIAAAAgAA" +
+ "AOMBAAAAIAAAAQAAAO4BAAAAEAAAAQAAAPwBAAA=");
+
+ public static void doTest(Transform t) {
+ t.sayHi("MethodChange");
+ try {
+ Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("MethodChange");
+ }
+}
diff --git a/test/921-hello-failure/src/MissingField.java b/test/921-hello-failure/src/MissingField.java
new file mode 100644
index 0000000000..2f643cc871
--- /dev/null
+++ b/test/921-hello-failure/src/MissingField.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 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.util.Base64;
+
+class MissingField {
+ // The following is a base64 encoding of the following class.
+ // class Transform4 {
+ // public Transform4(String s) { }
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFQoABgAOBwAPCAAQCgACABEHABIHABMBAAY8aW5pdD4BABUoTGphdmEvbGFuZy9T" +
+ "dHJpbmc7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFc2F5SGkBAApTb3VyY2VGaWxlAQAP" +
+ "VHJhbnNmb3JtNC5qYXZhDAAHABQBAA9qYXZhL2xhbmcvRXJyb3IBABVTaG91bGQgbm90IGJlIGNh" +
+ "bGxlZCEMAAcACAEAClRyYW5zZm9ybTQBABBqYXZhL2xhbmcvT2JqZWN0AQADKClWACAABQAGAAAA" +
+ "AAACAAEABwAIAAEACQAAAB0AAQACAAAABSq3AAGxAAAAAQAKAAAABgABAAAAAgABAAsACAABAAkA" +
+ "AAAiAAMAAgAAAAq7AAJZEgO3AAS/AAAAAQAKAAAABgABAAAABAABAAwAAAACAA0=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQDBVUVrMUEFx3lYkgJF54evq9vHvOUDZveUAgAAcAAAAHhWNBIAAAAAAAAAAAACAAAL" +
+ "AAAAcAAAAAUAAACcAAAAAgAAALAAAAAAAAAAAAAAAAQAAADIAAAAAQAAAOgAAACMAQAACAEAAEoB" +
+ "AABSAQAAYAEAAHMBAACHAQAAmwEAALIBAADDAQAAxgEAAMoBAADeAQAAAQAAAAIAAAADAAAABAAA" +
+ "AAcAAAAHAAAABAAAAAAAAAAIAAAABAAAAEQBAAAAAAEAAAAAAAAAAQAKAAAAAQABAAAAAAACAAAA" +
+ "AAAAAAAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAAPEBAAAAAAAAAgACAAEAAADlAQAABAAAAHAQAwAA" +
+ "AA4ABAACAAIAAADrAQAACQAAACIAAQAbAQUAAABwIAIAEAAnAAAAAQAAAAMABjxpbml0PgAMTFRy" +
+ "YW5zZm9ybTQ7ABFMamF2YS9sYW5nL0Vycm9yOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9s" +
+ "YW5nL1N0cmluZzsAFVNob3VsZCBub3QgYmUgY2FsbGVkIQAPVHJhbnNmb3JtNC5qYXZhAAFWAAJW" +
+ "TAASZW1pdHRlcjogamFjay00LjIyAAVzYXlIaQACAQAHDgAEAQAHDgAAAAEBAIGABIgCAQGgAgAM" +
+ "AAAAAAAAAAEAAAAAAAAAAQAAAAsAAABwAAAAAgAAAAUAAACcAAAAAwAAAAIAAACwAAAABQAAAAQA" +
+ "AADIAAAABgAAAAEAAADoAAAAASAAAAIAAAAIAQAAARAAAAEAAABEAQAAAiAAAAsAAABKAQAAAyAA" +
+ "AAIAAADlAQAAACAAAAEAAADxAQAAABAAAAEAAAAAAgAA");
+
+ public static void doTest(Transform4 t) {
+ t.sayHi("MissingField");
+ try {
+ Main.doCommonClassRedefinition(Transform4.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("MissingField");
+ }
+}
diff --git a/test/921-hello-failure/src/MissingMethod.java b/test/921-hello-failure/src/MissingMethod.java
new file mode 100644
index 0000000000..3f1925c9ad
--- /dev/null
+++ b/test/921-hello-failure/src/MissingMethod.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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.util.Base64;
+
+class MissingMethod {
+ // The following is a base64 encoding of the following class.
+ // class Transform3 {
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFQoABgAPBwAQCAARCgACABIHABMHABQBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP" +
+ "TGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3VyY2VG" +
+ "aWxlAQAPVHJhbnNmb3JtMy5qYXZhDAAHAAgBAA9qYXZhL2xhbmcvRXJyb3IBABVTaG91bGQgbm90" +
+ "IGJlIGNhbGxlZCEMAAcADAEAClRyYW5zZm9ybTMBABBqYXZhL2xhbmcvT2JqZWN0ACAABQAGAAAA" +
+ "AAACAAAABwAIAAEACQAAAB0AAQABAAAABSq3AAGxAAAAAQAKAAAABgABAAAAAgABAAsADAABAAkA" +
+ "AAAiAAMAAgAAAAq7AAJZEgO3AAS/AAAAAQAKAAAABgABAAAABAABAA0AAAACAA4=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQDnVQvyn7XrwDiCC/SE55zBCtEqk4pzA2mUAgAAcAAAAHhWNBIAAAAAAAAAAAACAAAL" +
+ "AAAAcAAAAAUAAACcAAAAAgAAALAAAAAAAAAAAAAAAAQAAADIAAAAAQAAAOgAAACMAQAACAEAAEoB" +
+ "AABSAQAAYAEAAHMBAACHAQAAmwEAALIBAADDAQAAxgEAAMoBAADeAQAAAQAAAAIAAAADAAAABAAA" +
+ "AAcAAAAHAAAABAAAAAAAAAAIAAAABAAAAEQBAAAAAAAAAAAAAAAAAQAKAAAAAQABAAAAAAACAAAA" +
+ "AAAAAAAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAAPABAAAAAAAAAQABAAEAAADlAQAABAAAAHAQAwAA" +
+ "AA4ABAACAAIAAADqAQAACQAAACIAAQAbAQUAAABwIAIAEAAnAAAAAQAAAAMABjxpbml0PgAMTFRy" +
+ "YW5zZm9ybTM7ABFMamF2YS9sYW5nL0Vycm9yOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9s" +
+ "YW5nL1N0cmluZzsAFVNob3VsZCBub3QgYmUgY2FsbGVkIQAPVHJhbnNmb3JtMy5qYXZhAAFWAAJW" +
+ "TAASZW1pdHRlcjogamFjay00LjI0AAVzYXlIaQACAAcOAAQBAAcOAAAAAQEAgIAEiAIBAaACAAAM" +
+ "AAAAAAAAAAEAAAAAAAAAAQAAAAsAAABwAAAAAgAAAAUAAACcAAAAAwAAAAIAAACwAAAABQAAAAQA" +
+ "AADIAAAABgAAAAEAAADoAAAAASAAAAIAAAAIAQAAARAAAAEAAABEAQAAAiAAAAsAAABKAQAAAyAA" +
+ "AAIAAADlAQAAACAAAAEAAADwAQAAABAAAAEAAAAAAgAA");
+
+ public static void doTest(Transform3 t) {
+ t.sayHi("MissingMethod");
+ try {
+ Main.doCommonClassRedefinition(Transform3.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("MissingMethod");
+ }
+}
diff --git a/test/921-hello-failure/src/NewField.java b/test/921-hello-failure/src/NewField.java
new file mode 100644
index 0000000000..c85b79e824
--- /dev/null
+++ b/test/921-hello-failure/src/NewField.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.util.Base64;
+
+class NewField {
+ // The following is a base64 encoding of the following class.
+ // class Transform {
+ // private Object field;
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFwoABgARBwASCAATCgACABQHABUHABYBAAVmaWVsZAEAEkxqYXZhL2xhbmcvT2Jq" +
+ "ZWN0OwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAVzYXlIaQEAFShM" +
+ "amF2YS9sYW5nL1N0cmluZzspVgEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwACQAKAQAP" +
+ "amF2YS9sYW5nL0Vycm9yAQAVU2hvdWxkIG5vdCBiZSBjYWxsZWQhDAAJAA4BAAlUcmFuc2Zvcm0B" +
+ "ABBqYXZhL2xhbmcvT2JqZWN0ACAABQAGAAAAAQACAAcACAAAAAIAAAAJAAoAAQALAAAAHQABAAEA" +
+ "AAAFKrcAAbEAAAABAAwAAAAGAAEAAAABAAEADQAOAAEACwAAACIAAwACAAAACrsAAlkSA7cABL8A" +
+ "AAABAAwAAAAGAAEAAAAEAAEADwAAAAIAEA==");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQBNWknL2iyjim487p0EIH/8V5OjOeLgw5e0AgAAcAAAAHhWNBIAAAAAAAAAABQCAAAM" +
+ "AAAAcAAAAAUAAACgAAAAAgAAALQAAAABAAAAzAAAAAQAAADUAAAAAQAAAPQAAACgAQAAFAEAAFYB" +
+ "AABeAQAAawEAAH4BAACSAQAApgEAAL0BAADNAQAA0AEAANQBAADoAQAA7wEAAAEAAAACAAAAAwAA" +
+ "AAQAAAAHAAAABwAAAAQAAAAAAAAACAAAAAQAAABQAQAAAAACAAoAAAAAAAAAAAAAAAAAAQALAAAA" +
+ "AQABAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAAAECAAAAAAAAAQABAAEAAAD2" +
+ "AQAABAAAAHAQAwAAAA4ABAACAAIAAAD7AQAACQAAACIAAQAbAQUAAABwIAIAEAAnAAAAAQAAAAMA" +
+ "Bjxpbml0PgALTFRyYW5zZm9ybTsAEUxqYXZhL2xhbmcvRXJyb3I7ABJMamF2YS9sYW5nL09iamVj" +
+ "dDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAVU2hvdWxkIG5vdCBiZSBjYWxsZWQhAA5UcmFuc2Zvcm0u" +
+ "amF2YQABVgACVkwAEmVtaXR0ZXI6IGphY2stNC4yMgAFZmllbGQABXNheUhpAAEABw4ABAEABw4A" +
+ "AAEBAQACAICABJQCAQGsAgAAAA0AAAAAAAAAAQAAAAAAAAABAAAADAAAAHAAAAACAAAABQAAAKAA" +
+ "AAADAAAAAgAAALQAAAAEAAAAAQAAAMwAAAAFAAAABAAAANQAAAAGAAAAAQAAAPQAAAABIAAAAgAA" +
+ "ABQBAAABEAAAAQAAAFABAAACIAAADAAAAFYBAAADIAAAAgAAAPYBAAAAIAAAAQAAAAECAAAAEAAA" +
+ "AQAAABQCAAA=");
+
+ public static void doTest(Transform t) {
+ t.sayHi("NewField");
+ try {
+ Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("NewField");
+ }
+}
diff --git a/test/921-hello-failure/src/NewMethod.java b/test/921-hello-failure/src/NewMethod.java
new file mode 100644
index 0000000000..5eac670c68
--- /dev/null
+++ b/test/921-hello-failure/src/NewMethod.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.util.Base64;
+
+class NewMethod {
+ // The following is a base64 encoding of the following class.
+ // class Transform {
+ // public void extraMethod() {}
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFgoABgAQBwARCAASCgACABMHABQHABUBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP" +
+ "TGluZU51bWJlclRhYmxlAQALZXh0cmFNZXRob2QBAAVzYXlIaQEAFShMamF2YS9sYW5nL1N0cmlu" +
+ "ZzspVgEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwABwAIAQAPamF2YS9sYW5nL0Vycm9y" +
+ "AQAVU2hvdWxkIG5vdCBiZSBjYWxsZWQhDAAHAA0BAAlUcmFuc2Zvcm0BABBqYXZhL2xhbmcvT2Jq" +
+ "ZWN0ACAABQAGAAAAAAADAAAABwAIAAEACQAAAB0AAQABAAAABSq3AAGxAAAAAQAKAAAABgABAAAA" +
+ "AQABAAsACAABAAkAAAAZAAAAAQAAAAGxAAAAAQAKAAAABgABAAAAAgABAAwADQABAAkAAAAiAAMA" +
+ "AgAAAAq7AAJZEgO3AAS/AAAAAQAKAAAABgABAAAABAABAA4AAAACAA8=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQBeV7dLAwN1GBTa/yRlkuiIQatNHghVdrnIAgAAcAAAAHhWNBIAAAAAAAAAADQCAAAM" +
+ "AAAAcAAAAAUAAACgAAAAAgAAALQAAAAAAAAAAAAAAAUAAADMAAAAAQAAAPQAAAC0AQAAFAEAAGoB" +
+ "AAByAQAAfwEAAJIBAACmAQAAugEAANEBAADhAQAA5AEAAOgBAAD8AQAACQIAAAEAAAACAAAAAwAA" +
+ "AAQAAAAHAAAABwAAAAQAAAAAAAAACAAAAAQAAABkAQAAAAAAAAAAAAAAAAAACgAAAAAAAQALAAAA" +
+ "AQABAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAACACAAAAAAAAAQABAAEAAAAQ" +
+ "AgAABAAAAHAQBAAAAA4AAQABAAAAAAAVAgAAAQAAAA4AAAAEAAIAAgAAABoCAAAJAAAAIgABABsB" +
+ "BQAAAHAgAwAQACcAAAABAAAAAwAGPGluaXQ+AAtMVHJhbnNmb3JtOwARTGphdmEvbGFuZy9FcnJv" +
+ "cjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABVTaG91bGQgbm90IGJl" +
+ "IGNhbGxlZCEADlRyYW5zZm9ybS5qYXZhAAFWAAJWTAASZW1pdHRlcjogamFjay00LjIyAAtleHRy" +
+ "YU1ldGhvZAAFc2F5SGkAAQAHDgACAAcOAAQBAAcOAAAAAQIAgIAElAIBAawCAQHAAgAADAAAAAAA" +
+ "AAABAAAAAAAAAAEAAAAMAAAAcAAAAAIAAAAFAAAAoAAAAAMAAAACAAAAtAAAAAUAAAAFAAAAzAAA" +
+ "AAYAAAABAAAA9AAAAAEgAAADAAAAFAEAAAEQAAABAAAAZAEAAAIgAAAMAAAAagEAAAMgAAADAAAA" +
+ "EAIAAAAgAAABAAAAIAIAAAAQAAABAAAANAIAAA==");
+
+ public static void doTest(Transform t) {
+ t.sayHi("NewMethod");
+ try {
+ Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("NewMethod");
+ }
+}
diff --git a/test/921-hello-failure/src/Transform3.java b/test/921-hello-failure/src/Transform3.java
new file mode 100644
index 0000000000..d2cb064956
--- /dev/null
+++ b/test/921-hello-failure/src/Transform3.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+class Transform3 {
+ public void extraMethod(String name) {
+ System.out.println("extraMethod - " + name);
+ }
+ public void sayHi(String name) {
+ System.out.println("hello2 - " + name);
+ }
+}
diff --git a/test/921-hello-failure/src/Transform4.java b/test/921-hello-failure/src/Transform4.java
new file mode 100644
index 0000000000..fd763386ba
--- /dev/null
+++ b/test/921-hello-failure/src/Transform4.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+class Transform4 {
+ private String greeting;
+ public Transform4(String hi) {
+ greeting = hi;
+ }
+ public void sayHi(String name) {
+ System.out.println("hello " + greeting + " - " + name);
+ }
+}
diff --git a/test/922-properties/run b/test/922-properties/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/922-properties/run
+++ b/test/922-properties/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/923-monitors/run b/test/923-monitors/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/923-monitors/run
+++ b/test/923-monitors/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/924-threads/run b/test/924-threads/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/924-threads/run
+++ b/test/924-threads/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/924-threads/src/Main.java b/test/924-threads/src/Main.java
index 29c4aa330c..f18d70e8e1 100644
--- a/test/924-threads/src/Main.java
+++ b/test/924-threads/src/Main.java
@@ -20,6 +20,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.CountDownLatch;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -162,8 +163,20 @@ public class Main {
private static void doAllThreadsTests() {
Thread[] threads = getAllThreads();
- Arrays.sort(threads, THREAD_COMP);
- System.out.println(Arrays.toString(threads));
+ List<Thread> threadList = new ArrayList<>(Arrays.asList(threads));
+
+ // Filter out JIT thread. It may or may not be there depending on configuration.
+ Iterator<Thread> it = threadList.iterator();
+ while (it.hasNext()) {
+ Thread t = it.next();
+ if (t.getName().startsWith("Jit thread pool worker")) {
+ it.remove();
+ break;
+ }
+ }
+
+ Collections.sort(threadList, THREAD_COMP);
+ System.out.println(threadList);
}
private static void doTLSTests() throws Exception {
diff --git a/test/925-threadgroups/run b/test/925-threadgroups/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/925-threadgroups/run
+++ b/test/925-threadgroups/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/925-threadgroups/src/Main.java b/test/925-threadgroups/src/Main.java
index 3d7a4ca740..bf7441f9bf 100644
--- a/test/925-threadgroups/src/Main.java
+++ b/test/925-threadgroups/src/Main.java
@@ -14,8 +14,12 @@
* limitations under the License.
*/
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
public class Main {
public static void main(String[] args) throws Exception {
@@ -64,10 +68,23 @@ public class Main {
Thread[] threads = (Thread[])data[0];
ThreadGroup[] groups = (ThreadGroup[])data[1];
- Arrays.sort(threads, THREAD_COMP);
+ List<Thread> threadList = new ArrayList<>(Arrays.asList(threads));
+
+ // Filter out JIT thread. It may or may not be there depending on configuration.
+ Iterator<Thread> it = threadList.iterator();
+ while (it.hasNext()) {
+ Thread t = it.next();
+ if (t.getName().startsWith("Jit thread pool worker")) {
+ it.remove();
+ break;
+ }
+ }
+
+ Collections.sort(threadList, THREAD_COMP);
+
Arrays.sort(groups, THREADGROUP_COMP);
System.out.println(tg.getName() + ":");
- System.out.println(" " + Arrays.toString(threads));
+ System.out.println(" " + threadList);
System.out.println(" " + Arrays.toString(groups));
if (tg.getParent() != null) {
diff --git a/test/926-multi-obsolescence/run b/test/926-multi-obsolescence/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/926-multi-obsolescence/run
+++ b/test/926-multi-obsolescence/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/927-timers/run b/test/927-timers/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/927-timers/run
+++ b/test/927-timers/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/928-jni-table/run b/test/928-jni-table/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/928-jni-table/run
+++ b/test/928-jni-table/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/929-search/run b/test/929-search/run
index 0a8d0672f6..67923a7984 100755
--- a/test/929-search/run
+++ b/test/929-search/run
@@ -17,7 +17,5 @@
# This test checks whether dex files can be injected into parent classloaders. App images preload
# classes, which will make the injection moot. Turn off app images to avoid the issue.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti \
+./default-run "$@" --jvmti \
--no-app-image
diff --git a/test/930-hello-retransform/run b/test/930-hello-retransform/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/930-hello-retransform/run
+++ b/test/930-hello-retransform/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/931-agent-thread/run b/test/931-agent-thread/run
index 0a8d0672f6..67923a7984 100755
--- a/test/931-agent-thread/run
+++ b/test/931-agent-thread/run
@@ -17,7 +17,5 @@
# This test checks whether dex files can be injected into parent classloaders. App images preload
# classes, which will make the injection moot. Turn off app images to avoid the issue.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti \
+./default-run "$@" --jvmti \
--no-app-image
diff --git a/test/932-transform-saves/run b/test/932-transform-saves/run
index 4379349cb2..c6e62ae6cd 100755
--- a/test/932-transform-saves/run
+++ b/test/932-transform-saves/run
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti
+./default-run "$@" --jvmti
diff --git a/test/933-misc-events/run b/test/933-misc-events/run
index 0a8d0672f6..67923a7984 100755
--- a/test/933-misc-events/run
+++ b/test/933-misc-events/run
@@ -17,7 +17,5 @@
# This test checks whether dex files can be injected into parent classloaders. App images preload
# classes, which will make the injection moot. Turn off app images to avoid the issue.
-./default-run "$@" --experimental agents \
- --experimental runtime-plugins \
- --jvmti \
+./default-run "$@" --jvmti \
--no-app-image
diff --git a/test/934-load-transform/build b/test/934-load-transform/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/934-load-transform/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/934-load-transform/expected.txt b/test/934-load-transform/expected.txt
new file mode 100644
index 0000000000..2b60207f03
--- /dev/null
+++ b/test/934-load-transform/expected.txt
@@ -0,0 +1 @@
+Goodbye
diff --git a/test/934-load-transform/info.txt b/test/934-load-transform/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/934-load-transform/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/934-load-transform/run b/test/934-load-transform/run
new file mode 100755
index 0000000000..adb1a1c507
--- /dev/null
+++ b/test/934-load-transform/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti --no-app-image
diff --git a/test/934-load-transform/src-ex/TestMain.java b/test/934-load-transform/src-ex/TestMain.java
new file mode 100644
index 0000000000..33be9cd09d
--- /dev/null
+++ b/test/934-load-transform/src-ex/TestMain.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+public class TestMain {
+ public static void runTest() {
+ new Transform().sayHi();
+ }
+}
diff --git a/test/934-load-transform/src-ex/Transform.java b/test/934-load-transform/src-ex/Transform.java
new file mode 100644
index 0000000000..f624c3ac99
--- /dev/null
+++ b/test/934-load-transform/src-ex/Transform.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class Transform {
+ public void sayHi() {
+ throw new Error("Should not be called!");
+ }
+}
diff --git a/test/934-load-transform/src/Main.java b/test/934-load-transform/src/Main.java
new file mode 100644
index 0000000000..de312b03da
--- /dev/null
+++ b/test/934-load-transform/src/Main.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 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.*;
+import java.util.Base64;
+
+class Main {
+ public static String TEST_NAME = "934-load-transform";
+
+ /**
+ * base64 encoded class/dex file for
+ * class Transform {
+ * public void sayHi() {
+ * System.out.println("Goodbye");
+ * }
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUB" +
+ "AA9MaW5lTnVtYmVyVGFibGUBAAVzYXlIaQEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwA" +
+ "BwAIBwAWDAAXABgBAAdHb29kYnllBwAZDAAaABsBAAlUcmFuc2Zvcm0BABBqYXZhL2xhbmcvT2Jq" +
+ "ZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2ph" +
+ "dmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACAABQAG" +
+ "AAAAAAACAAAABwAIAAEACQAAAB0AAQABAAAABSq3AAGxAAAAAQAKAAAABgABAAAAEQABAAsACAAB" +
+ "AAkAAAAlAAIAAQAAAAmyAAISA7YABLEAAAABAAoAAAAKAAIAAAATAAgAFAABAAwAAAACAA0=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQCLXSBQ5FiS3f16krSYZFF8xYZtFVp0GRXMAgAAcAAAAHhWNBIAAAAAAAAAACwCAAAO" +
+ "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACsAQAAIAEAAGIB" +
+ "AABqAQAAcwEAAIABAACXAQAAqwEAAL8BAADTAQAA4wEAAOYBAADqAQAA/gEAAAMCAAAMAgAAAgAA" +
+ "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" +
+ "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAAB4CAAAA" +
+ "AAAAAQABAAEAAAATAgAABAAAAHAQAwAAAA4AAwABAAIAAAAYAgAACQAAAGIAAAAbAQEAAABuIAIA" +
+ "EAAOAAAAAQAAAAMABjxpbml0PgAHR29vZGJ5ZQALTFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50" +
+ "U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xh" +
+ "bmcvU3lzdGVtOwAOVHJhbnNmb3JtLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTMuMzYAA291" +
+ "dAAHcHJpbnRsbgAFc2F5SGkAEQAHDgATAAcOhQAAAAEBAICABKACAQG4Ag0AAAAAAAAAAQAAAAAA" +
+ "AAABAAAADgAAAHAAAAACAAAABgAAAKgAAAADAAAAAgAAAMAAAAAEAAAAAQAAANgAAAAFAAAABAAA" +
+ "AOAAAAAGAAAAAQAAAAABAAABIAAAAgAAACABAAABEAAAAQAAAFwBAAACIAAADgAAAGIBAAADIAAA" +
+ "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA=");
+
+ public static ClassLoader getClassLoaderFor(String location) throws Exception {
+ try {
+ Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader");
+ Constructor<?> ctor = class_loader_class.getConstructor(String.class, ClassLoader.class);
+ /* on Dalvik, this is a DexFile; otherwise, it's null */
+ return (ClassLoader)ctor.newInstance(location + "/" + TEST_NAME + "-ex.jar",
+ Main.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ // Running on RI. Use URLClassLoader.
+ return new java.net.URLClassLoader(
+ new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") });
+ }
+ }
+
+ public static void main(String[] args) {
+ // Don't pop transformations. Make sure that even if 2 threads race to define the class both
+ // will get the same result.
+ setPopRetransformations(false);
+ addCommonTransformationResult("Transform", CLASS_BYTES, DEX_BYTES);
+ enableCommonRetransformation(true);
+ try {
+ /* this is the "alternate" DEX/Jar file */
+ ClassLoader new_loader = getClassLoaderFor(System.getenv("DEX_LOCATION"));
+ Class<?> klass = (Class<?>)new_loader.loadClass("TestMain");
+ if (klass == null) {
+ throw new AssertionError("loadClass failed");
+ }
+ Method run_test = klass.getMethod("runTest");
+ run_test.invoke(null);
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ private static native void setPopRetransformations(boolean should_pop);
+ // Transforms the class
+ private static native void enableCommonRetransformation(boolean enable);
+ private static native void addCommonTransformationResult(String target_name,
+ byte[] class_bytes,
+ byte[] dex_bytes);
+}
diff --git a/test/935-non-retransformable/build b/test/935-non-retransformable/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/935-non-retransformable/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/935-non-retransformable/expected.txt b/test/935-non-retransformable/expected.txt
new file mode 100644
index 0000000000..ccd50a66a0
--- /dev/null
+++ b/test/935-non-retransformable/expected.txt
@@ -0,0 +1,6 @@
+Hello
+Hello
+Goodbye
+Hello
+Hello
+Goodbye
diff --git a/test/935-non-retransformable/info.txt b/test/935-non-retransformable/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/935-non-retransformable/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/935-non-retransformable/run b/test/935-non-retransformable/run
new file mode 100755
index 0000000000..adb1a1c507
--- /dev/null
+++ b/test/935-non-retransformable/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti --no-app-image
diff --git a/test/935-non-retransformable/src-ex/TestMain.java b/test/935-non-retransformable/src-ex/TestMain.java
new file mode 100644
index 0000000000..d412fba37a
--- /dev/null
+++ b/test/935-non-retransformable/src-ex/TestMain.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 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.Method;
+
+public class TestMain {
+ public static void runTest() throws Exception {
+ Transform t = new Transform();
+ // Call functions with reflection. Since the sayGoodbye function does not exist in the
+ // LTransform; when we compile this for the first time we need to use reflection.
+ Method hi = Transform.class.getMethod("sayHi");
+ Method bye = Transform.class.getMethod("sayGoodbye");
+ hi.invoke(t);
+ t.sayHi();
+ bye.invoke(t);
+ }
+}
diff --git a/test/935-non-retransformable/src-ex/Transform.java b/test/935-non-retransformable/src-ex/Transform.java
new file mode 100644
index 0000000000..f624c3ac99
--- /dev/null
+++ b/test/935-non-retransformable/src-ex/Transform.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class Transform {
+ public void sayHi() {
+ throw new Error("Should not be called!");
+ }
+}
diff --git a/test/935-non-retransformable/src/Main.java b/test/935-non-retransformable/src/Main.java
new file mode 100644
index 0000000000..82ba197b7e
--- /dev/null
+++ b/test/935-non-retransformable/src/Main.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 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.*;
+import java.util.Base64;
+
+class Main {
+ public static String TEST_NAME = "935-non-retransformable";
+
+ /**
+ * base64 encoded class/dex file for
+ * class Transform {
+ * public void sayHi() {
+ * System.out.println("Hello");
+ * }
+ * public void sayGoodbye() {
+ * System.out.println("Goodbye");
+ * }
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAHwoABwAQCQARABIIABMKABQAFQgAFgcAFwcAGAEABjxpbml0PgEAAygpVgEABENv" +
+ "ZGUBAA9MaW5lTnVtYmVyVGFibGUBAAVzYXlIaQEACnNheUdvb2RieWUBAApTb3VyY2VGaWxlAQAO" +
+ "VHJhbnNmb3JtLmphdmEMAAgACQcAGQwAGgAbAQAFSGVsbG8HABwMAB0AHgEAB0dvb2RieWUBAAlU" +
+ "cmFuc2Zvcm0BABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxq" +
+ "YXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExq" +
+ "YXZhL2xhbmcvU3RyaW5nOylWACAABgAHAAAAAAADAAAACAAJAAEACgAAAB0AAQABAAAABSq3AAGx" +
+ "AAAAAQALAAAABgABAAAAAQABAAwACQABAAoAAAAlAAIAAQAAAAmyAAISA7YABLEAAAABAAsAAAAK" +
+ "AAIAAAADAAgABAABAA0ACQABAAoAAAAlAAIAAQAAAAmyAAISBbYABLEAAAABAAsAAAAKAAIAAAAG" +
+ "AAgABwABAA4AAAACAA8=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQDpaN+7jX/ZLl9Jr0HAEV7nqL1YDuakKakgAwAAcAAAAHhWNBIAAAAAAAAAAIACAAAQ" +
+ "AAAAcAAAAAYAAACwAAAAAgAAAMgAAAABAAAA4AAAAAUAAADoAAAAAQAAABABAADwAQAAMAEAAJYB" +
+ "AACeAQAApwEAAK4BAAC7AQAA0gEAAOYBAAD6AQAADgIAAB4CAAAhAgAAJQIAADkCAAA+AgAARwIA" +
+ "AFMCAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABQAAAAAAAAAKAAAABQAAAJABAAAEAAEA" +
+ "DAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAADwAAAAEAAQANAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAA" +
+ "AAAACAAAAAAAAABrAgAAAAAAAAEAAQABAAAAWgIAAAQAAABwEAQAAAAOAAMAAQACAAAAXwIAAAkA" +
+ "AABiAAAAGwEBAAAAbiADABAADgAAAAMAAQACAAAAZQIAAAkAAABiAAAAGwECAAAAbiADABAADgAA" +
+ "AAEAAAADAAY8aW5pdD4AB0dvb2RieWUABUhlbGxvAAtMVHJhbnNmb3JtOwAVTGphdmEvaW8vUHJp" +
+ "bnRTdHJlYW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEv" +
+ "bGFuZy9TeXN0ZW07AA5UcmFuc2Zvcm0uamF2YQABVgACVkwAEmVtaXR0ZXI6IGphY2stNC4yMgAD" +
+ "b3V0AAdwcmludGxuAApzYXlHb29kYnllAAVzYXlIaQABAAcOAAYABw6HAAMABw6HAAAAAQIAgIAE" +
+ "sAIBAcgCAQHsAgAAAA0AAAAAAAAAAQAAAAAAAAABAAAAEAAAAHAAAAACAAAABgAAALAAAAADAAAA" +
+ "AgAAAMgAAAAEAAAAAQAAAOAAAAAFAAAABQAAAOgAAAAGAAAAAQAAABABAAABIAAAAwAAADABAAAB" +
+ "EAAAAQAAAJABAAACIAAAEAAAAJYBAAADIAAAAwAAAFoCAAAAIAAAAQAAAGsCAAAAEAAAAQAAAIAC" +
+ "AAA=");
+
+
+ public static ClassLoader getClassLoaderFor(String location) throws Exception {
+ try {
+ Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader");
+ Constructor<?> ctor = class_loader_class.getConstructor(String.class, ClassLoader.class);
+ /* on Dalvik, this is a DexFile; otherwise, it's null */
+ return (ClassLoader)ctor.newInstance(location + "/" + TEST_NAME + "-ex.jar",
+ Main.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ // Running on RI. Use URLClassLoader.
+ return new java.net.URLClassLoader(
+ new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") });
+ }
+ }
+
+ public static void main(String[] args) {
+ setPopRetransformations(false);
+ addCommonTransformationResult("Transform", CLASS_BYTES, DEX_BYTES);
+ enableCommonRetransformation(true);
+ try {
+ /* this is the "alternate" DEX/Jar file */
+ ClassLoader new_loader = getClassLoaderFor(System.getenv("DEX_LOCATION"));
+ Class<?> klass = (Class<?>)new_loader.loadClass("TestMain");
+ if (klass == null) {
+ throw new AssertionError("loadClass failed");
+ }
+ Method run_test = klass.getMethod("runTest");
+ run_test.invoke(null);
+
+ // Remove the original transformation. It has been used by now.
+ popTransformationFor("Transform");
+ // Make sure we don't get called for transformation again.
+ addCommonTransformationResult("Transform", new byte[0], new byte[0]);
+ doCommonClassRetransformation(new_loader.loadClass("Transform"));
+ run_test.invoke(null);
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ // Transforms the class
+ private static native void doCommonClassRetransformation(Class<?>... classes);
+ private static native void enableCommonRetransformation(boolean enable);
+ private static native void addCommonTransformationResult(String target_name,
+ byte[] class_bytes,
+ byte[] dex_bytes);
+ private static native void setPopRetransformations(boolean should_pop);
+ private static native void popTransformationFor(String target_name);
+}
diff --git a/test/936-search-onload/build b/test/936-search-onload/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/936-search-onload/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/936-search-onload/expected.txt b/test/936-search-onload/expected.txt
new file mode 100644
index 0000000000..2eec8e1aac
--- /dev/null
+++ b/test/936-search-onload/expected.txt
@@ -0,0 +1,3 @@
+B was loaded with boot classloader
+A was loaded with system classloader
+Done
diff --git a/test/936-search-onload/info.txt b/test/936-search-onload/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/936-search-onload/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/936-search-onload/run b/test/936-search-onload/run
new file mode 100755
index 0000000000..67923a7984
--- /dev/null
+++ b/test/936-search-onload/run
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+# This test checks whether dex files can be injected into parent classloaders. App images preload
+# classes, which will make the injection moot. Turn off app images to avoid the issue.
+
+./default-run "$@" --jvmti \
+ --no-app-image
diff --git a/test/936-search-onload/search_onload.cc b/test/936-search-onload/search_onload.cc
new file mode 100644
index 0000000000..2286a467d3
--- /dev/null
+++ b/test/936-search-onload/search_onload.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "search_onload.h"
+
+#include <inttypes.h>
+
+#include "android-base/stringprintf.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "jni.h"
+#include "openjdkjvmti/jvmti.h"
+#include "ScopedUtfChars.h"
+
+#include "ti-agent/common_helper.h"
+#include "ti-agent/common_load.h"
+
+namespace art {
+namespace Test936SearchOnload {
+
+jint OnLoad(JavaVM* vm,
+ char* options ATTRIBUTE_UNUSED,
+ void* reserved ATTRIBUTE_UNUSED) {
+ if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
+ printf("Unable to get jvmti env!\n");
+ return 1;
+ }
+ SetAllCapabilities(jvmti_env);
+
+ char* dex_loc = getenv("DEX_LOCATION");
+ std::string dex1 = android::base::StringPrintf("%s/936-search-onload.jar", dex_loc);
+ std::string dex2 = android::base::StringPrintf("%s/936-search-onload-ex.jar", dex_loc);
+
+ jvmtiError result = jvmti_env->AddToBootstrapClassLoaderSearch(dex1.c_str());
+ if (result != JVMTI_ERROR_NONE) {
+ printf("Could not add to bootstrap classloader.\n");
+ return 1;
+ }
+
+ result = jvmti_env->AddToSystemClassLoaderSearch(dex2.c_str());
+ if (result != JVMTI_ERROR_NONE) {
+ printf("Could not add to system classloader.\n");
+ return 1;
+ }
+
+ return JNI_OK;
+}
+
+} // namespace Test936SearchOnload
+} // namespace art
diff --git a/test/936-search-onload/search_onload.h b/test/936-search-onload/search_onload.h
new file mode 100644
index 0000000000..e55689252d
--- /dev/null
+++ b/test/936-search-onload/search_onload.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_TEST_936_SEARCH_ONLOAD_SEARCH_ONLOAD_H_
+#define ART_TEST_936_SEARCH_ONLOAD_SEARCH_ONLOAD_H_
+
+#include <jni.h>
+
+namespace art {
+namespace Test936SearchOnload {
+
+jint OnLoad(JavaVM* vm, char* options, void* reserved);
+
+} // namespace Test936SearchOnload
+} // namespace art
+
+#endif // ART_TEST_936_SEARCH_ONLOAD_SEARCH_ONLOAD_H_
diff --git a/test/936-search-onload/src-ex/A.java b/test/936-search-onload/src-ex/A.java
new file mode 100644
index 0000000000..64acb2fcfe
--- /dev/null
+++ b/test/936-search-onload/src-ex/A.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+public class A {
+} \ No newline at end of file
diff --git a/test/936-search-onload/src/B.java b/test/936-search-onload/src/B.java
new file mode 100644
index 0000000000..f1458c3bca
--- /dev/null
+++ b/test/936-search-onload/src/B.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+public class B {
+} \ No newline at end of file
diff --git a/test/936-search-onload/src/Main.java b/test/936-search-onload/src/Main.java
new file mode 100644
index 0000000000..2e7a87193b
--- /dev/null
+++ b/test/936-search-onload/src/Main.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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.util.Arrays;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ doTest();
+ }
+
+ private static void doTest() throws Exception {
+ doTest(true, "B");
+ doTest(false, "A");
+ System.out.println("Done");
+ }
+
+ private static void doTest(boolean boot, String className) throws Exception {
+ ClassLoader expectedClassLoader;
+ if (boot) {
+ expectedClassLoader = Object.class.getClassLoader();
+ } else {
+ expectedClassLoader = ClassLoader.getSystemClassLoader();
+ }
+
+ Class<?> c = Class.forName(className, false, ClassLoader.getSystemClassLoader());
+ if (c.getClassLoader() != expectedClassLoader) {
+ throw new RuntimeException(className + "(" + boot + "): " +
+ c.getClassLoader() + " vs " + expectedClassLoader);
+ } else {
+ System.out.println(className + " was loaded with " + (boot ? "boot" : "system") +
+ " classloader");
+ }
+ }
+}
diff --git a/test/937-hello-retransform-package/build b/test/937-hello-retransform-package/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/937-hello-retransform-package/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/937-hello-retransform-package/expected.txt b/test/937-hello-retransform-package/expected.txt
new file mode 100644
index 0000000000..4774b81b49
--- /dev/null
+++ b/test/937-hello-retransform-package/expected.txt
@@ -0,0 +1,2 @@
+hello
+Goodbye
diff --git a/test/937-hello-retransform-package/info.txt b/test/937-hello-retransform-package/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/937-hello-retransform-package/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/937-hello-retransform-package/run b/test/937-hello-retransform-package/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/937-hello-retransform-package/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/937-hello-retransform-package/src/Main.java b/test/937-hello-retransform-package/src/Main.java
new file mode 100644
index 0000000000..4b9271b4f4
--- /dev/null
+++ b/test/937-hello-retransform-package/src/Main.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 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.util.Base64;
+
+import testing.*;
+public class Main {
+
+ /**
+ * base64 encoded class/dex file for
+ * package testing;
+ * class Transform {
+ * public void sayHi() {
+ * System.out.println("Goodbye");
+ * }
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUB" +
+ "AA9MaW5lTnVtYmVyVGFibGUBAAVzYXlIaQEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwA" +
+ "BwAIBwAWDAAXABgBAAdHb29kYnllBwAZDAAaABsBABF0ZXN0aW5nL1RyYW5zZm9ybQEAEGphdmEv" +
+ "bGFuZy9PYmplY3QBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJl" +
+ "YW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7" +
+ "KVYAIQAFAAYAAAAAAAIAAQAHAAgAAQAJAAAAHQABAAEAAAAFKrcAAbEAAAABAAoAAAAGAAEAAAAC" +
+ "AAEACwAIAAEACQAAACUAAgABAAAACbIAAhIDtgAEsQAAAAEACgAAAAoAAgAAAAQACAAFAAEADAAA" +
+ "AAIADQ==");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQBhYIi3Gs9Nn/GN1fCzF+aFQ0AbhA1h1WHUAgAAcAAAAHhWNBIAAAAAAAAAADQCAAAO" +
+ "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAAC0AQAAIAEAAGIB" +
+ "AABqAQAAcwEAAIoBAACeAQAAsgEAAMYBAADbAQAA6wEAAO4BAADyAQAABgIAAAsCAAAUAgAAAgAA" +
+ "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAAAwAAAAsAAAAAAAEA" +
+ "DAAAAAEAAAAAAAAABAAAAAAAAAAEAAAADQAAAAQAAAABAAAAAQAAAAAAAAAHAAAAAAAAACYCAAAA" +
+ "AAAAAQABAAEAAAAbAgAABAAAAHAQAQAAAA4AAwABAAIAAAAgAgAACQAAAGIAAAAbAQEAAABuIAAA" +
+ "EAAOAAAAAQAAAAIABjxpbml0PgAHR29vZGJ5ZQAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2" +
+ "YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07ABNM" +
+ "dGVzdGluZy9UcmFuc2Zvcm07AA5UcmFuc2Zvcm0uamF2YQABVgACVkwAEmVtaXR0ZXI6IGphY2st" +
+ "NC4yMgADb3V0AAdwcmludGxuAAVzYXlIaQACAAcOAAQABw6HAAAAAQECgYAEoAIDAbgCDQAAAAAA" +
+ "AAABAAAAAAAAAAEAAAAOAAAAcAAAAAIAAAAGAAAAqAAAAAMAAAACAAAAwAAAAAQAAAABAAAA2AAA" +
+ "AAUAAAAEAAAA4AAAAAYAAAABAAAAAAEAAAEgAAACAAAAIAEAAAEQAAABAAAAXAEAAAIgAAAOAAAA" +
+ "YgEAAAMgAAACAAAAGwIAAAAgAAABAAAAJgIAAAAQAAABAAAANAIAAA==");
+
+ public static void main(String[] args) {
+ doTest(new Transform());
+ }
+
+ public static void doTest(Transform t) {
+ t.sayHi();
+ addCommonTransformationResult("testing/Transform", CLASS_BYTES, DEX_BYTES);
+ enableCommonRetransformation(true);
+ doCommonClassRetransformation(Transform.class);
+ t.sayHi();
+ }
+
+ // Transforms the class
+ private static native void doCommonClassRetransformation(Class<?>... target);
+ private static native void enableCommonRetransformation(boolean enable);
+ private static native void addCommonTransformationResult(String target_name,
+ byte[] class_bytes,
+ byte[] dex_bytes);
+}
diff --git a/test/937-hello-retransform-package/src/Transform.java b/test/937-hello-retransform-package/src/Transform.java
new file mode 100644
index 0000000000..db92612299
--- /dev/null
+++ b/test/937-hello-retransform-package/src/Transform.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package testing;
+public class Transform {
+ public void sayHi() {
+ System.out.println("hello");
+ }
+}
diff --git a/test/938-load-transform-bcp/build b/test/938-load-transform-bcp/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/938-load-transform-bcp/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/938-load-transform-bcp/expected.txt b/test/938-load-transform-bcp/expected.txt
new file mode 100644
index 0000000000..16c3f8f726
--- /dev/null
+++ b/test/938-load-transform-bcp/expected.txt
@@ -0,0 +1,2 @@
+ol.foo() -> 'This is foo for val=123'
+ol.toString() -> 'This is toString() for val=123'
diff --git a/test/938-load-transform-bcp/info.txt b/test/938-load-transform-bcp/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/938-load-transform-bcp/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/938-load-transform-bcp/run b/test/938-load-transform-bcp/run
new file mode 100755
index 0000000000..adb1a1c507
--- /dev/null
+++ b/test/938-load-transform-bcp/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti --no-app-image
diff --git a/test/938-load-transform-bcp/src-ex/TestMain.java b/test/938-load-transform-bcp/src-ex/TestMain.java
new file mode 100644
index 0000000000..3757a0f778
--- /dev/null
+++ b/test/938-load-transform-bcp/src-ex/TestMain.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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.Method;
+import java.util.OptionalLong;
+public class TestMain {
+ public static void runTest() {
+ // This should be our redefined OptionalLong.
+ OptionalLong ol = OptionalLong.of(123);
+ try {
+ // OptionalLong is a class that is unlikely to be used by the time this test starts.
+ Method foo = OptionalLong.class.getMethod("foo");
+ System.out.println("ol.foo() -> '" + (String)foo.invoke(ol) + "'");
+ System.out.println("ol.toString() -> '" + ol.toString() + "'");
+ } catch (Exception e) {
+ System.out.println(
+ "Exception occured (did something load OptionalLong before this test method!: "
+ + e.toString());
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/938-load-transform-bcp/src/Main.java b/test/938-load-transform-bcp/src/Main.java
new file mode 100644
index 0000000000..548489939e
--- /dev/null
+++ b/test/938-load-transform-bcp/src/Main.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2016 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.*;
+import java.util.Base64;
+
+class Main {
+ public static String TEST_NAME = "938-load-transform-bcp";
+
+ /**
+ * base64 encoded class/dex file for
+ *
+ * // Yes this version of OptionalLong is not compatible with the real one but since it isn't used
+ * // for anything in the runtime initialization it should be fine.
+ *
+ * package java.util;
+ * public final class OptionalLong {
+ * private long val;
+ *
+ * private OptionalLong(long abc) {
+ * this.val = abc;
+ * }
+ *
+ * public static OptionalLong of(long abc) {
+ * return new OptionalLong(abc);
+ * }
+ *
+ * public String foo() {
+ * return "This is foo for val=" + val;
+ * }
+ *
+ * public String toString() {
+ * return "This is toString() for val=" + val;
+ * }
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAKQoADAAaCQADABsHABwKAAMAHQcAHgoABQAaCAAfCgAFACAKAAUAIQoABQAiCAAj" +
+ "BwAkAQADdmFsAQABSgEABjxpbml0PgEABChKKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAC" +
+ "b2YBABsoSilMamF2YS91dGlsL09wdGlvbmFsTG9uZzsBAANmb28BABQoKUxqYXZhL2xhbmcvU3Ry" +
+ "aW5nOwEACHRvU3RyaW5nAQAKU291cmNlRmlsZQEAEU9wdGlvbmFsTG9uZy5qYXZhDAAPACUMAA0A" +
+ "DgEAFmphdmEvdXRpbC9PcHRpb25hbExvbmcMAA8AEAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVy" +
+ "AQAUVGhpcyBpcyBmb28gZm9yIHZhbD0MACYAJwwAJgAoDAAXABYBABtUaGlzIGlzIHRvU3RyaW5n" +
+ "KCkgZm9yIHZhbD0BABBqYXZhL2xhbmcvT2JqZWN0AQADKClWAQAGYXBwZW5kAQAtKExqYXZhL2xh" +
+ "bmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAcKEopTGphdmEvbGFuZy9TdHJp" +
+ "bmdCdWlsZGVyOwAxAAMADAAAAAEAAgANAA4AAAAEAAIADwAQAAEAEQAAACoAAwADAAAACiq3AAEq" +
+ "H7UAArEAAAABABIAAAAOAAMAAAAFAAQABgAJAAcACQATABQAAQARAAAAIQAEAAIAAAAJuwADWR63" +
+ "AASwAAAAAQASAAAABgABAAAACgABABUAFgABABEAAAAvAAMAAQAAABe7AAVZtwAGEge2AAgqtAAC" +
+ "tgAJtgAKsAAAAAEAEgAAAAYAAQAAAA4AAQAXABYAAQARAAAALwADAAEAAAAXuwAFWbcABhILtgAI" +
+ "KrQAArYACbYACrAAAAABABIAAAAGAAEAAAASAAEAGAAAAAIAGQ==");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQAOe/TYJCvVthTToFA3tveMDhwTo7uDf0IcBAAAcAAAAHhWNBIAAAAAAAAAAHwDAAAU" +
+ "AAAAcAAAAAYAAADAAAAABgAAANgAAAABAAAAIAEAAAkAAAAoAQAAAQAAAHABAACMAgAAkAEAAFYC" +
+ "AABeAgAAYQIAAGQCAABoAgAAbAIAAIACAACUAgAArwIAAMkCAADcAgAA8gIAAA8DAAASAwAAFgMA" +
+ "AB4DAAAyAwAANwMAADsDAABFAwAAAQAAAAUAAAAGAAAABwAAAAgAAAAMAAAAAgAAAAIAAAAAAAAA" +
+ "AwAAAAMAAABIAgAABAAAAAMAAABQAgAAAwAAAAQAAABIAgAADAAAAAUAAAAAAAAADQAAAAUAAABI" +
+ "AgAABAAAABMAAAABAAQAAAAAAAMABAAAAAAAAwABAA4AAAADAAIADgAAAAMAAAASAAAABAAFAAAA" +
+ "AAAEAAAAEAAAAAQAAwARAAAABAAAABIAAAAEAAAAEQAAAAEAAAAAAAAACQAAAAAAAABiAwAAAAAA" +
+ "AAQAAwABAAAASgMAAAYAAABwEAAAAQBaEgAADgAEAAIAAwAAAFIDAAAGAAAAIgAEAHAwBQAgAxEA" +
+ "BQABAAMAAABYAwAAFwAAACIAAwBwEAEAAAAbAQoAAABuIAMAEAAMAFNCAABuMAIAIAMMAG4QBAAA" +
+ "AAwAEQAAAAUAAQADAAAAXQMAABcAAAAiAAMAcBABAAAAGwELAAAAbiADABAADABTQgAAbjACACAD" +
+ "DABuEAQAAAAMABEAAAABAAAAAAAAAAEAAAACAAY8aW5pdD4AAUoAAUwAAkxKAAJMTAASTGphdmEv" +
+ "bGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRl" +
+ "cjsAGExqYXZhL3V0aWwvT3B0aW9uYWxMb25nOwART3B0aW9uYWxMb25nLmphdmEAFFRoaXMgaXMg" +
+ "Zm9vIGZvciB2YWw9ABtUaGlzIGlzIHRvU3RyaW5nKCkgZm9yIHZhbD0AAVYAAlZKAAZhcHBlbmQA" +
+ "EmVtaXR0ZXI6IGphY2stNC4yMgADZm9vAAJvZgAIdG9TdHJpbmcAA3ZhbAAFAQAHDjwtAAoBAAcO" +
+ "AA4ABw4AEgAHDgAAAQICAAIFgoAEkAMCCawDBgHIAwIBiAQAAA0AAAAAAAAAAQAAAAAAAAABAAAA" +
+ "FAAAAHAAAAACAAAABgAAAMAAAAADAAAABgAAANgAAAAEAAAAAQAAACABAAAFAAAACQAAACgBAAAG" +
+ "AAAAAQAAAHABAAABIAAABAAAAJABAAABEAAAAgAAAEgCAAACIAAAFAAAAFYCAAADIAAABAAAAEoD" +
+ "AAAAIAAAAQAAAGIDAAAAEAAAAQAAAHwDAAA=");
+
+ public static ClassLoader getClassLoaderFor(String location) throws Exception {
+ try {
+ Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader");
+ Constructor<?> ctor = class_loader_class.getConstructor(String.class, ClassLoader.class);
+ return (ClassLoader)ctor.newInstance(location + "/" + TEST_NAME + "-ex.jar",
+ Main.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ // Running on RI. Use URLClassLoader.
+ return new java.net.URLClassLoader(
+ new java.net.URL[] { new java.net.URL("file://" + location + "/classes-ex/") });
+ }
+ }
+
+ public static void main(String[] args) {
+ setPopRetransformations(false);
+ addCommonTransformationResult("java/util/OptionalLong", CLASS_BYTES, DEX_BYTES);
+ enableCommonRetransformation(true);
+ try {
+ /* this is the "alternate" DEX/Jar file */
+ ClassLoader new_loader = getClassLoaderFor(System.getenv("DEX_LOCATION"));
+ Class<?> klass = (Class<?>)new_loader.loadClass("TestMain");
+ if (klass == null) {
+ throw new AssertionError("loadClass failed");
+ }
+ Method run_test = klass.getMethod("runTest");
+ run_test.invoke(null);
+ } catch (Exception e) {
+ System.out.println(e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ private static native void setPopRetransformations(boolean should_pop);
+ // Transforms the class
+ private static native void enableCommonRetransformation(boolean enable);
+ private static native void addCommonTransformationResult(String target_name,
+ byte[] class_bytes,
+ byte[] dex_bytes);
+}
diff --git a/test/939-hello-transformation-bcp/build b/test/939-hello-transformation-bcp/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/939-hello-transformation-bcp/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/939-hello-transformation-bcp/expected.txt b/test/939-hello-transformation-bcp/expected.txt
new file mode 100644
index 0000000000..90fd25828d
--- /dev/null
+++ b/test/939-hello-transformation-bcp/expected.txt
@@ -0,0 +1,3 @@
+ol.toString() -> 'OptionalLong[-559038737]'
+Redefining OptionalLong!
+ol.toString() -> 'Redefined OptionalLong!'
diff --git a/test/939-hello-transformation-bcp/info.txt b/test/939-hello-transformation-bcp/info.txt
new file mode 100644
index 0000000000..d230a382bd
--- /dev/null
+++ b/test/939-hello-transformation-bcp/info.txt
@@ -0,0 +1,6 @@
+Tests basic functions in the jvmti plugin.
+
+Note this function is reliant on the definition of java.util.OptionalLong not
+changing. If this classes definition changes we will need to update this class
+so that the CLASS_BYTES and DEX_BYTES fields contain dex/class bytes for an
+OptionalLong with all the same methods and fields.
diff --git a/test/939-hello-transformation-bcp/run b/test/939-hello-transformation-bcp/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/939-hello-transformation-bcp/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/939-hello-transformation-bcp/src/Main.java b/test/939-hello-transformation-bcp/src/Main.java
new file mode 100644
index 0000000000..bdf7f592ef
--- /dev/null
+++ b/test/939-hello-transformation-bcp/src/Main.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 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.util.Base64;
+import java.util.OptionalLong;
+public class Main {
+
+ /**
+ * This is the base64 encoded class/dex.
+ *
+ * package java.util;
+ * import java.util.function.LongConsumer;
+ * import java.util.function.LongSupplier;
+ * import java.util.function.Supplier;
+ * public final class OptionalLong {
+ * // Make sure we have a <clinit> function since the real implementation of OptionalLong does.
+ * static { EMPTY = null; }
+ * private static final OptionalLong EMPTY;
+ * private final boolean isPresent;
+ * private final long value;
+ * private OptionalLong() { isPresent = false; value = 0; }
+ * private OptionalLong(long l) { this(); }
+ * public static OptionalLong empty() { return null; }
+ * public static OptionalLong of(long value) { return null; }
+ * public long getAsLong() { return 0; }
+ * public boolean isPresent() { return false; }
+ * public void ifPresent(LongConsumer c) { }
+ * public long orElse(long l) { return 0; }
+ * public long orElseGet(LongSupplier s) { return 0; }
+ * public<X extends Throwable> long orElseThrow(Supplier<X> s) throws X { return 0; }
+ * public boolean equals(Object o) { return false; }
+ * public int hashCode() { return 0; }
+ * public String toString() { return "Redefined OptionalLong!"; }
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAOAoACAAwCQAHADEJAAcAMgoABwAwCAAzCQAHADQHADUHADYBAAVFTVBUWQEAGExq" +
+ "YXZhL3V0aWwvT3B0aW9uYWxMb25nOwEACWlzUHJlc2VudAEAAVoBAAV2YWx1ZQEAAUoBAAY8aW5p" +
+ "dD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAEKEopVgEABWVtcHR5AQAaKClMamF2" +
+ "YS91dGlsL09wdGlvbmFsTG9uZzsBAAJvZgEAGyhKKUxqYXZhL3V0aWwvT3B0aW9uYWxMb25nOwEA" +
+ "CWdldEFzTG9uZwEAAygpSgEAAygpWgEACWlmUHJlc2VudAEAJChMamF2YS91dGlsL2Z1bmN0aW9u" +
+ "L0xvbmdDb25zdW1lcjspVgEABm9yRWxzZQEABChKKUoBAAlvckVsc2VHZXQBACQoTGphdmEvdXRp" +
+ "bC9mdW5jdGlvbi9Mb25nU3VwcGxpZXI7KUoBAAtvckVsc2VUaHJvdwEAIChMamF2YS91dGlsL2Z1" +
+ "bmN0aW9uL1N1cHBsaWVyOylKAQAKRXhjZXB0aW9ucwcANwEACVNpZ25hdHVyZQEAQjxYOkxqYXZh" +
+ "L2xhbmcvVGhyb3dhYmxlOz4oTGphdmEvdXRpbC9mdW5jdGlvbi9TdXBwbGllcjxUWDs+OylKXlRY" +
+ "OwEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEACGhhc2hDb2RlAQADKClJAQAIdG9T" +
+ "dHJpbmcBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEACDxjbGluaXQ+AQAKU291cmNlRmlsZQEAEU9w" +
+ "dGlvbmFsTG9uZy5qYXZhDAAPABAMAAsADAwADQAOAQAXUmVkZWZpbmVkIE9wdGlvbmFsTG9uZyEM" +
+ "AAkACgEAFmphdmEvdXRpbC9PcHRpb25hbExvbmcBABBqYXZhL2xhbmcvT2JqZWN0AQATamF2YS9s" +
+ "YW5nL1Rocm93YWJsZQAxAAcACAAAAAMAGgAJAAoAAAASAAsADAAAABIADQAOAAAADgACAA8AEAAB" +
+ "ABEAAAAnAAMAAQAAAA8qtwABKgO1AAIqCbUAA7EAAAABABIAAAAGAAEAAAALAAIADwATAAEAEQAA" +
+ "AB0AAQADAAAABSq3AASxAAAAAQASAAAABgABAAAADAAJABQAFQABABEAAAAaAAEAAAAAAAIBsAAA" +
+ "AAEAEgAAAAYAAQAAAA0ACQAWABcAAQARAAAAGgABAAIAAAACAbAAAAABABIAAAAGAAEAAAAOAAEA" +
+ "GAAZAAEAEQAAABoAAgABAAAAAgmtAAAAAQASAAAABgABAAAADwABAAsAGgABABEAAAAaAAEAAQAA" +
+ "AAIDrAAAAAEAEgAAAAYAAQAAABAAAQAbABwAAQARAAAAGQAAAAIAAAABsQAAAAEAEgAAAAYAAQAA" +
+ "ABEAAQAdAB4AAQARAAAAGgACAAMAAAACCa0AAAABABIAAAAGAAEAAAASAAEAHwAgAAEAEQAAABoA" +
+ "AgACAAAAAgmtAAAAAQASAAAABgABAAAAEwABACEAIgADABEAAAAaAAIAAgAAAAIJrQAAAAEAEgAA" +
+ "AAYAAQAAABQAIwAAAAQAAQAkACUAAAACACYAAQAnACgAAQARAAAAGgABAAIAAAACA6wAAAABABIA" +
+ "AAAGAAEAAAAVAAEAKQAqAAEAEQAAABoAAQABAAAAAgOsAAAAAQASAAAABgABAAAAFgABACsALAAB" +
+ "ABEAAAAbAAEAAQAAAAMSBbAAAAABABIAAAAGAAEAAAAXAAgALQAQAAEAEQAAAB0AAQAAAAAABQGz" +
+ "AAaxAAAAAQASAAAABgABAAAABwABAC4AAAACAC8=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQCvAoivSJqk6GdYOgJmvrM/b2/flxhw99q8BwAAcAAAAHhWNBIAAAAAAAAAAPgGAAAq" +
+ "AAAAcAAAAA0AAAAYAQAADQAAAEwBAAADAAAA6AEAAA8AAAAAAgAAAQAAAHgCAAAkBQAAmAIAACoE" +
+ "AAA4BAAAPQQAAEcEAABPBAAAUwQAAFoEAABdBAAAYAQAAGQEAABoBAAAawQAAG8EAACOBAAAqgQA" +
+ "AL4EAADSBAAA6QQAAAMFAAAmBQAASQUAAGcFAACGBQAAmQUAALIFAAC1BQAAuQUAAL0FAADABQAA" +
+ "xAUAANgFAADfBQAA5wUAAPIFAAD8BQAABwYAABIGAAAWBgAAHgYAACkGAAA2BgAAQAYAAAYAAAAH" +
+ "AAAADAAAAA0AAAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAVAAAAGAAAABsAAAAGAAAAAAAAAAAA" +
+ "AAAHAAAAAQAAAAAAAAAIAAAAAQAAAAQEAAAJAAAAAQAAAAwEAAAJAAAAAQAAABQEAAAKAAAABQAA" +
+ "AAAAAAAKAAAABwAAAAAAAAALAAAABwAAAAQEAAAYAAAACwAAAAAAAAAZAAAACwAAAAQEAAAaAAAA" +
+ "CwAAABwEAAAbAAAADAAAAAAAAAAcAAAADAAAACQEAAAHAAcABQAAAAcADAAjAAAABwABACkAAAAE" +
+ "AAgAAwAAAAcACAACAAAABwAIAAMAAAAHAAkAAwAAAAcABgAeAAAABwAMAB8AAAAHAAEAIAAAAAcA" +
+ "AAAhAAAABwAKACIAAAAHAAsAIwAAAAcABwAkAAAABwACACUAAAAHAAMAJgAAAAcABAAnAAAABwAF" +
+ "ACgAAAAHAAAAEQAAAAQAAAAAAAAAFgAAAOwDAACtBgAAAAAAAAIAAACVBgAApQYAAAEAAAAAAAAA" +
+ "RwYAAAQAAAASAGkAAAAOAAMAAQABAAAATQYAAAsAAABwEAAAAgASAFwgAQAWAAAAWiACAA4AAAAD" +
+ "AAMAAQAAAFIGAAAEAAAAcBACAAAADgABAAAAAAAAAFgGAAACAAAAEgARAAMAAgAAAAAAXQYAAAIA" +
+ "AAASABEAAwACAAAAAABjBgAAAgAAABIADwADAAEAAAAAAGkGAAADAAAAFgAAABAAAAACAAEAAAAA" +
+ "AG4GAAACAAAAEgAPAAIAAgAAAAAAcwYAAAEAAAAOAAAAAgABAAAAAAB5BgAAAgAAABIADwAFAAMA" +
+ "AAAAAH4GAAADAAAAFgAAABAAAAAEAAIAAAAAAIQGAAADAAAAFgAAABAAAAAEAAIAAAAAAIoGAAAD" +
+ "AAAAFgAAABAAAAACAAEAAAAAAJAGAAAEAAAAGwAXAAAAEQAAAAAAAAAAAAEAAAAAAAAADQAAAJgC" +
+ "AAABAAAAAQAAAAEAAAAJAAAAAQAAAAoAAAABAAAACAAAAAEAAAAEAAw8VFg7PjspSl5UWDsAAzxY" +
+ "OgAIPGNsaW5pdD4ABjxpbml0PgACPigABUVNUFRZAAFJAAFKAAJKSgACSkwAAUwAAkxKAB1MZGFs" +
+ "dmlrL2Fubm90YXRpb24vU2lnbmF0dXJlOwAaTGRhbHZpay9hbm5vdGF0aW9uL1Rocm93czsAEkxq" +
+ "YXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABVMamF2YS9sYW5nL1Rocm93YWJs" +
+ "ZTsAGExqYXZhL3V0aWwvT3B0aW9uYWxMb25nOwAhTGphdmEvdXRpbC9mdW5jdGlvbi9Mb25nQ29u" +
+ "c3VtZXI7ACFMamF2YS91dGlsL2Z1bmN0aW9uL0xvbmdTdXBwbGllcjsAHExqYXZhL3V0aWwvZnVu" +
+ "Y3Rpb24vU3VwcGxpZXIAHUxqYXZhL3V0aWwvZnVuY3Rpb24vU3VwcGxpZXI7ABFPcHRpb25hbExv" +
+ "bmcuamF2YQAXUmVkZWZpbmVkIE9wdGlvbmFsTG9uZyEAAVYAAlZKAAJWTAABWgACWkwAEmVtaXR0" +
+ "ZXI6IGphY2stNC4yMgAFZW1wdHkABmVxdWFscwAJZ2V0QXNMb25nAAhoYXNoQ29kZQAJaWZQcmVz" +
+ "ZW50AAlpc1ByZXNlbnQAAm9mAAZvckVsc2UACW9yRWxzZUdldAALb3JFbHNlVGhyb3cACHRvU3Ry" +
+ "aW5nAAV2YWx1ZQAHAAcOOQALAAcOAAwBAAcOAA0ABw4ADgEABw4AFQEABw4ADwAHDgAWAAcOABEB" +
+ "AAcOABAABw4AEgEABw4AEwEABw4AFAEABw4AFwAHDgACAgEpHAUXARcQFwQXFBcAAgMBKRwBGAYB" +
+ "AgUJABoBEgESAYiABKQFAYKABLwFAYKABOQFAQn8BQYJkAYFAaQGAQG4BgEB0AYBAeQGAQH4BgIB" +
+ "jAcBAaQHAQG8BwEB1AcAAAAQAAAAAAAAAAEAAAAAAAAAAQAAACoAAABwAAAAAgAAAA0AAAAYAQAA" +
+ "AwAAAA0AAABMAQAABAAAAAMAAADoAQAABQAAAA8AAAAAAgAABgAAAAEAAAB4AgAAAxAAAAEAAACY" +
+ "AgAAASAAAA4AAACkAgAABiAAAAEAAADsAwAAARAAAAUAAAAEBAAAAiAAACoAAAAqBAAAAyAAAA4A" +
+ "AABHBgAABCAAAAIAAACVBgAAACAAAAEAAACtBgAAABAAAAEAAAD4BgAA");
+
+ public static void main(String[] args) {
+ // OptionalLong is a class that is unlikely to be used by the time this test starts and is not
+ // likely to be changed in any meaningful way in the future.
+ OptionalLong ol = OptionalLong.of(0xDEADBEEF);
+ System.out.println("ol.toString() -> '" + ol.toString() + "'");
+ System.out.println("Redefining OptionalLong!");
+ doCommonClassRedefinition(OptionalLong.class, CLASS_BYTES, DEX_BYTES);
+ System.out.println("ol.toString() -> '" + ol.toString() + "'");
+ }
+
+ // Transforms the class
+ private static native void doCommonClassRedefinition(Class<?> target,
+ byte[] class_file,
+ byte[] dex_file);
+}
diff --git a/test/940-recursive-obsolete/build b/test/940-recursive-obsolete/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/940-recursive-obsolete/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/940-recursive-obsolete/expected.txt b/test/940-recursive-obsolete/expected.txt
new file mode 100644
index 0000000000..18ffc25d8a
--- /dev/null
+++ b/test/940-recursive-obsolete/expected.txt
@@ -0,0 +1,21 @@
+hello2
+hello1
+Not doing anything here
+hello0
+goodbye0
+goodbye1
+goodbye2
+hello2
+hello1
+transforming calling function
+Hello0 - transformed
+Goodbye0 - transformed
+goodbye1
+goodbye2
+Hello2 - transformed
+Hello1 - transformed
+Not doing anything here
+Hello0 - transformed
+Goodbye0 - transformed
+Goodbye1 - transformed
+Goodbye2 - transformed
diff --git a/test/940-recursive-obsolete/info.txt b/test/940-recursive-obsolete/info.txt
new file mode 100644
index 0000000000..c8b892cedd
--- /dev/null
+++ b/test/940-recursive-obsolete/info.txt
@@ -0,0 +1 @@
+Tests basic obsolete method support
diff --git a/test/940-recursive-obsolete/run b/test/940-recursive-obsolete/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/940-recursive-obsolete/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/940-recursive-obsolete/src/Main.java b/test/940-recursive-obsolete/src/Main.java
new file mode 100644
index 0000000000..3766906a89
--- /dev/null
+++ b/test/940-recursive-obsolete/src/Main.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 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.util.Base64;
+
+public class Main {
+
+ // class Transform {
+ // public void sayHi(int recur, Runnable r) {
+ // System.out.println("Hello" + recur + " - transformed");
+ // if (recur == 1) {
+ // r.run();
+ // sayHi(recur - 1, r);
+ // } else if (recur != 0) {
+ // sayHi(recur - 1, r);
+ // }
+ // System.out.println("Goodbye" + recur + " - transformed");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQANwoADwAZCQAaABsHABwKAAMAGQgAHQoAAwAeCgADAB8IACAKAAMAIQoAIgAjCwAk" +
+ "ACUKAA4AJggAJwcAKAcAKQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUB" +
+ "AAVzYXlIaQEAGChJTGphdmEvbGFuZy9SdW5uYWJsZTspVgEADVN0YWNrTWFwVGFibGUBAApTb3Vy" +
+ "Y2VGaWxlAQAOVHJhbnNmb3JtLmphdmEMABAAEQcAKgwAKwAsAQAXamF2YS9sYW5nL1N0cmluZ0J1" +
+ "aWxkZXIBAAVIZWxsbwwALQAuDAAtAC8BAA4gLSB0cmFuc2Zvcm1lZAwAMAAxBwAyDAAzADQHADUM" +
+ "ADYAEQwAFAAVAQAHR29vZGJ5ZQEACVRyYW5zZm9ybQEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZh" +
+ "L2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQAGYXBwZW5kAQAtKExq" +
+ "YXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAcKEkpTGphdmEvbGFu" +
+ "Zy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAUKClMamF2YS9sYW5nL1N0cmluZzsBABNqYXZh" +
+ "L2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEAEmphdmEv" +
+ "bGFuZy9SdW5uYWJsZQEAA3J1bgAgAA4ADwAAAAAAAgAAABAAEQABABIAAAAdAAEAAQAAAAUqtwAB" +
+ "sQAAAAEAEwAAAAYAAQAAAAEAAQAUABUAAQASAAAAnQADAAMAAABfsgACuwADWbcABBIFtgAGG7YA" +
+ "BxIItgAGtgAJtgAKGwSgABQsuQALAQAqGwRkLLYADKcADxuZAAsqGwRkLLYADLIAArsAA1m3AAQS" +
+ "DbYABhu2AAcSCLYABrYACbYACrEAAAACABMAAAAiAAgAAAADAB4ABAAjAAUAKQAGADQABwA4AAgA" +
+ "QAAKAF4ACwAWAAAABAACNAsAAQAXAAAAAgAY");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQA3pkIgnymz2/eri+mp2dyZo3jolQmaRPKEBAAAcAAAAHhWNBIAAAAAAAAAAOQDAAAa" +
+ "AAAAcAAAAAkAAADYAAAABgAAAPwAAAABAAAARAEAAAkAAABMAQAAAQAAAJQBAADQAgAAtAEAAJwC" +
+ "AACsAgAAtAIAAL0CAADEAgAAxwIAAMoCAADOAgAA0gIAAN8CAAD2AgAACgMAACADAAA0AwAATwMA" +
+ "AGMDAABzAwAAdgMAAHsDAAB/AwAAhwMAAJsDAACgAwAAqQMAAK4DAAC1AwAABAAAAAgAAAAJAAAA" +
+ "CgAAAAsAAAAMAAAADQAAAA4AAAAQAAAABQAAAAUAAAAAAAAABgAAAAYAAACEAgAABwAAAAYAAACM" +
+ "AgAAEAAAAAgAAAAAAAAAEQAAAAgAAACUAgAAEgAAAAgAAACMAgAABwACABUAAAABAAMAAQAAAAEA" +
+ "BAAYAAAAAgAFABYAAAADAAMAAQAAAAQAAwAXAAAABgADAAEAAAAGAAEAEwAAAAYAAgATAAAABgAA" +
+ "ABkAAAABAAAAAAAAAAMAAAAAAAAADwAAAAAAAADWAwAAAAAAAAEAAQABAAAAvwMAAAQAAABwEAMA" +
+ "AAAOAAYAAwADAAAAxAMAAFQAAABiAAAAIgEGAHAQBQABABsCAwAAAG4gBwAhAAwBbiAGAEEADAEb" +
+ "AgAAAABuIAcAIQAMAW4QCAABAAwBbiACABAAEhAzBCsAchAEAAUA2AAE/24wAQADBWIAAAAiAQYA" +
+ "cBAFAAEAGwICAAAAbiAHACEADAFuIAYAQQAMARsCAAAAAG4gBwAhAAwBbhAIAAEADAFuIAIAEAAO" +
+ "ADgE3//YAAT/bjABAAMFKNgBAAAAAAAAAAEAAAAFAAAAAgAAAAAABAAOIC0gdHJhbnNmb3JtZWQA" +
+ "Bjxpbml0PgAHR29vZGJ5ZQAFSGVsbG8AAUkAAUwAAkxJAAJMTAALTFRyYW5zZm9ybTsAFUxqYXZh" +
+ "L2lvL1ByaW50U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9sYW5nL1J1bm5hYmxl" +
+ "OwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7ABJMamF2YS9s" +
+ "YW5nL1N5c3RlbTsADlRyYW5zZm9ybS5qYXZhAAFWAANWSUwAAlZMAAZhcHBlbmQAEmVtaXR0ZXI6" +
+ "IGphY2stNC4yNAADb3V0AAdwcmludGxuAANydW4ABXNheUhpAAh0b1N0cmluZwABAAcOAAMCAAAH" +
+ "DgEgDzw8XQEgDxktAAAAAQEAgIAEtAMBAcwDDQAAAAAAAAABAAAAAAAAAAEAAAAaAAAAcAAAAAIA" +
+ "AAAJAAAA2AAAAAMAAAAGAAAA/AAAAAQAAAABAAAARAEAAAUAAAAJAAAATAEAAAYAAAABAAAAlAEA" +
+ "AAEgAAACAAAAtAEAAAEQAAADAAAAhAIAAAIgAAAaAAAAnAIAAAMgAAACAAAAvwMAAAAgAAABAAAA" +
+ "1gMAAAAQAAABAAAA5AMAAA==");
+
+ public static void main(String[] args) {
+ doTest(new Transform());
+ }
+
+ public static void doTest(Transform t) {
+ t.sayHi(2, () -> { System.out.println("Not doing anything here"); });
+ t.sayHi(2, () -> {
+ System.out.println("transforming calling function");
+ doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ });
+ t.sayHi(2, () -> { System.out.println("Not doing anything here"); });
+ }
+
+ // Transforms the class
+ private static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+}
diff --git a/test/940-recursive-obsolete/src/Transform.java b/test/940-recursive-obsolete/src/Transform.java
new file mode 100644
index 0000000000..97522cddf6
--- /dev/null
+++ b/test/940-recursive-obsolete/src/Transform.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class Transform {
+ public void sayHi(int recur, Runnable r) {
+ System.out.println("hello" + recur);
+ if (recur == 1) {
+ r.run();
+ sayHi(recur - 1, r);
+ } else if (recur != 0) {
+ sayHi(recur - 1, r);
+ }
+ System.out.println("goodbye" + recur);
+ }
+}
diff --git a/test/941-recurive-obsolete-jit/build b/test/941-recurive-obsolete-jit/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/941-recurive-obsolete-jit/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/941-recurive-obsolete-jit/expected.txt b/test/941-recurive-obsolete-jit/expected.txt
new file mode 100644
index 0000000000..086f7b03dc
--- /dev/null
+++ b/test/941-recurive-obsolete-jit/expected.txt
@@ -0,0 +1,22 @@
+hello2
+hello1
+Not doing anything here
+hello0
+goodbye0
+goodbye1
+goodbye2
+hello2
+hello1
+transforming calling function
+Hello0 - transformed
+Goodbye0 - transformed
+goodbye1
+goodbye2
+Hello2 - transformed
+Hello1 - transformed
+Not doing anything here
+Hello0 - transformed
+Goodbye0 - transformed
+Goodbye1 - transformed
+Goodbye2 - transformed
+
diff --git a/test/941-recurive-obsolete-jit/info.txt b/test/941-recurive-obsolete-jit/info.txt
new file mode 100644
index 0000000000..c8b892cedd
--- /dev/null
+++ b/test/941-recurive-obsolete-jit/info.txt
@@ -0,0 +1 @@
+Tests basic obsolete method support
diff --git a/test/941-recurive-obsolete-jit/run b/test/941-recurive-obsolete-jit/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/941-recurive-obsolete-jit/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/941-recurive-obsolete-jit/src/Main.java b/test/941-recurive-obsolete-jit/src/Main.java
new file mode 100644
index 0000000000..f6d6416b55
--- /dev/null
+++ b/test/941-recurive-obsolete-jit/src/Main.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016 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.util.Base64;
+import java.util.function.Consumer;
+import java.lang.reflect.Method;
+
+public class Main {
+
+ // import java.util.function.Consumer;
+ // class Transform {
+ // public void sayHi(int recur, Consumer<String> reporter, Runnable r) {
+ // reporter.accept("Hello" + recur + " - transformed");
+ // if (recur == 1) {
+ // r.run();
+ // sayHi(recur - 1, reporter, r);
+ // } else if (recur != 0) {
+ // sayHi(recur - 1, reporter, r);
+ // }
+ // reporter.accept("Goodbye" + recur + " - transformed");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAMwoADgAaBwAbCgACABoIABwKAAIAHQoAAgAeCAAfCgACACALACEAIgsAIwAkCgAN" +
+ "ACUIACYHACcHACgBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFc2F5" +
+ "SGkBADUoSUxqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7TGphdmEvbGFuZy9SdW5uYWJsZTsp" +
+ "VgEADVN0YWNrTWFwVGFibGUBAAlTaWduYXR1cmUBAEkoSUxqYXZhL3V0aWwvZnVuY3Rpb24vQ29u" +
+ "c3VtZXI8TGphdmEvbGFuZy9TdHJpbmc7PjtMamF2YS9sYW5nL1J1bm5hYmxlOylWAQAKU291cmNl" +
+ "RmlsZQEADlRyYW5zZm9ybS5qYXZhDAAPABABABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgEABUhl" +
+ "bGxvDAApACoMACkAKwEADiAtIHRyYW5zZm9ybWVkDAAsAC0HAC4MAC8AMAcAMQwAMgAQDAATABQB" +
+ "AAdHb29kYnllAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAEABmFwcGVuZAEALShMamF2" +
+ "YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAHChJKUxqYXZhL2xhbmcv" +
+ "U3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAbamF2YS91" +
+ "dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAQAGYWNjZXB0AQAVKExqYXZhL2xhbmcvT2JqZWN0OylWAQAS" +
+ "amF2YS9sYW5nL1J1bm5hYmxlAQADcnVuACAADQAOAAAAAAACAAAADwAQAAEAEQAAAB0AAQABAAAA" +
+ "BSq3AAGxAAAAAQASAAAABgABAAAAAgABABMAFAACABEAAACfAAQABAAAAGEsuwACWbcAAxIEtgAF" +
+ "G7YABhIHtgAFtgAIuQAJAgAbBKAAFS25AAoBACobBGQsLbYAC6cAEBuZAAwqGwRkLC22AAssuwAC" +
+ "WbcAAxIMtgAFG7YABhIHtgAFtgAIuQAJAgCxAAAAAgASAAAAIgAIAAAABAAeAAUAIwAGACkABwA1" +
+ "AAgAOQAJAEIACwBgAAwAFQAAAAQAAjUMABYAAAACABcAAQAYAAAAAgAZ");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQA7uevryhDgvad3G3EACTdspZGfNKv2i3kkBQAAcAAAAHhWNBIAAAAAAAAAAGwEAAAf" +
+ "AAAAcAAAAAkAAADsAAAABgAAABABAAAAAAAAAAAAAAkAAABYAQAAAQAAAKABAABkAwAAwAEAAMoC" +
+ "AADaAgAA3gIAAOICAADlAgAA7QIAAPECAAD6AgAAAQMAAAQDAAAHAwAACwMAAA8DAAAcAwAAOwMA" +
+ "AE8DAABlAwAAeQMAAJQDAACyAwAA0QMAAOEDAADkAwAA6gMAAO4DAAD2AwAA/gMAABIEAAAXBAAA" +
+ "HgQAACgEAAAIAAAADAAAAA0AAAAOAAAADwAAABAAAAARAAAAEwAAABUAAAAJAAAABQAAAAAAAAAK" +
+ "AAAABgAAAKgCAAALAAAABgAAALACAAAVAAAACAAAAAAAAAAWAAAACAAAALgCAAAXAAAACAAAAMQC" +
+ "AAABAAMABAAAAAEABAAcAAAAAwADAAQAAAAEAAMAGwAAAAYAAwAEAAAABgABABkAAAAGAAIAGQAA" +
+ "AAYAAAAdAAAABwAFABgAAAABAAAAAAAAAAMAAAAAAAAAFAAAAJACAABbBAAAAAAAAAEAAABHBAAA" +
+ "AQABAAEAAAAvBAAABAAAAHAQAgAAAA4ABgAEAAQAAAA0BAAAUAAAACIABgBwEAQAAAAbAQcAAABu" +
+ "IAYAEAAMAG4gBQAwAAwAGwEAAAAAbiAGABAADABuEAcAAAAMAHIgCAAEABIQMwMpAHIQAwAFANgA" +
+ "A/9uQAEAAlQiAAYAcBAEAAAAGwEGAAAAbiAGABAADABuIAUAMAAMABsBAAAAAG4gBgAQAAwAbhAH" +
+ "AAAADAByIAgABAAOADgD4f/YAAP/bkABAAJUKNoAAAAAAAAAAAEAAAAAAAAAAQAAAMABAAABAAAA" +
+ "AAAAAAEAAAAFAAAAAwAAAAAABwAEAAAAAQAAAAMADiAtIHRyYW5zZm9ybWVkAAIoSQACKVYAATwA" +
+ "Bjxpbml0PgACPjsAB0dvb2RieWUABUhlbGxvAAFJAAFMAAJMSQACTEwAC0xUcmFuc2Zvcm07AB1M" +
+ "ZGFsdmlrL2Fubm90YXRpb24vU2lnbmF0dXJlOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9s" +
+ "YW5nL1J1bm5hYmxlOwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5nL1N0cmluZ0J1aWxk" +
+ "ZXI7ABxMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAB1MamF2YS91dGlsL2Z1bmN0aW9uL0Nv" +
+ "bnN1bWVyOwAOVHJhbnNmb3JtLmphdmEAAVYABFZJTEwAAlZMAAZhY2NlcHQABmFwcGVuZAASZW1p" +
+ "dHRlcjogamFjay00LjI0AANydW4ABXNheUhpAAh0b1N0cmluZwAFdmFsdWUAAgAHDgAEAwAAAAcO" +
+ "AR4PPDxdAR4PGS0AAgIBHhwHFwEXEhcDFxAXBRcPFwIAAAEBAICABMgDAQHgAwAAAA8AAAAAAAAA" +
+ "AQAAAAAAAAABAAAAHwAAAHAAAAACAAAACQAAAOwAAAADAAAABgAAABABAAAFAAAACQAAAFgBAAAG" +
+ "AAAAAQAAAKABAAADEAAAAQAAAMABAAABIAAAAgAAAMgBAAAGIAAAAQAAAJACAAABEAAABAAAAKgC" +
+ "AAACIAAAHwAAAMoCAAADIAAAAgAAAC8EAAAEIAAAAQAAAEcEAAAAIAAAAQAAAFsEAAAAEAAAAQAA" +
+ "AGwEAAA=");
+
+ // A class that we can use to keep track of the output of this test.
+ private static class TestWatcher implements Consumer<String> {
+ private StringBuilder sb;
+ public TestWatcher() {
+ sb = new StringBuilder();
+ }
+
+ @Override
+ public void accept(String s) {
+ sb.append(s);
+ sb.append('\n');
+ }
+
+ public String getOutput() {
+ return sb.toString();
+ }
+
+ public void clear() {
+ sb = new StringBuilder();
+ }
+ }
+
+ public static void main(String[] args) {
+ doTest(new Transform());
+ }
+
+ private static boolean retry = false;
+
+ public static void doTest(Transform t) {
+ final TestWatcher reporter = new TestWatcher();
+ Method say_hi_method;
+ // Figure out if we can even JIT at all.
+ final boolean has_jit = hasJit();
+ try {
+ say_hi_method = Transform.class.getDeclaredMethod(
+ "sayHi", int.class, Consumer.class, Runnable.class);
+ } catch (Exception e) {
+ System.out.println("Unable to find methods!");
+ e.printStackTrace();
+ return;
+ }
+ // Makes sure the stack is the way we want it for the test and does the redefinition. It will
+ // set the retry boolean to true if we need to go around again due to jit code being GCd.
+ Runnable do_redefinition = () -> {
+ if (has_jit && Main.isInterpretedFunction(say_hi_method, true)) {
+ // Try again. We are not running the right jitted methods/cannot redefine them now.
+ retry = true;
+ } else {
+ // Actually do the redefinition. The stack looks good.
+ retry = false;
+ reporter.accept("transforming calling function");
+ doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ }
+ };
+ do {
+ // Run ensureJitCompiled here since it might get GCd
+ ensureJitCompiled(Transform.class, "sayHi");
+ // Clear output.
+ reporter.clear();
+ t.sayHi(2, reporter, () -> { reporter.accept("Not doing anything here"); });
+ t.sayHi(2, reporter, do_redefinition);
+ t.sayHi(2, reporter, () -> { reporter.accept("Not doing anything here"); });
+ } while(retry);
+ System.out.println(reporter.getOutput());
+ }
+
+ private static native boolean hasJit();
+
+ private static native boolean isInterpretedFunction(Method m, boolean require_deoptimizable);
+
+ private static native void ensureJitCompiled(Class c, String name);
+
+ // Transforms the class
+ private static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+}
diff --git a/test/941-recurive-obsolete-jit/src/Transform.java b/test/941-recurive-obsolete-jit/src/Transform.java
new file mode 100644
index 0000000000..e6a913a391
--- /dev/null
+++ b/test/941-recurive-obsolete-jit/src/Transform.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 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.util.function.Consumer;
+class Transform {
+ public void sayHi(int recur, Consumer<String> c, Runnable r) {
+ c.accept("hello" + recur);
+ if (recur == 1) {
+ r.run();
+ sayHi(recur - 1, c, r);
+ } else if (recur != 0) {
+ sayHi(recur - 1, c, r);
+ }
+ c.accept("goodbye" + recur);
+ }
+}
diff --git a/test/942-private-recursive/build b/test/942-private-recursive/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/942-private-recursive/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/942-private-recursive/expected.txt b/test/942-private-recursive/expected.txt
new file mode 100644
index 0000000000..18ffc25d8a
--- /dev/null
+++ b/test/942-private-recursive/expected.txt
@@ -0,0 +1,21 @@
+hello2
+hello1
+Not doing anything here
+hello0
+goodbye0
+goodbye1
+goodbye2
+hello2
+hello1
+transforming calling function
+Hello0 - transformed
+Goodbye0 - transformed
+goodbye1
+goodbye2
+Hello2 - transformed
+Hello1 - transformed
+Not doing anything here
+Hello0 - transformed
+Goodbye0 - transformed
+Goodbye1 - transformed
+Goodbye2 - transformed
diff --git a/test/942-private-recursive/info.txt b/test/942-private-recursive/info.txt
new file mode 100644
index 0000000000..c8b892cedd
--- /dev/null
+++ b/test/942-private-recursive/info.txt
@@ -0,0 +1 @@
+Tests basic obsolete method support
diff --git a/test/942-private-recursive/run b/test/942-private-recursive/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/942-private-recursive/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/942-private-recursive/src/Main.java b/test/942-private-recursive/src/Main.java
new file mode 100644
index 0000000000..8cbab7bac3
--- /dev/null
+++ b/test/942-private-recursive/src/Main.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 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.util.Base64;
+
+public class Main {
+
+ // class Transform {
+ // public void sayHi(int recur, Runnable r) {
+ // privateSayHi(recur, r);
+ // }
+ // private void privateSayHi(int recur, Runnable r) {
+ // System.out.println("Hello" + recur + " - transformed");
+ // if (recur == 1) {
+ // r.run();
+ // privateSayHi(recur - 1, r);
+ // } else if (recur != 0) {
+ // privateSayHi(recur - 1, r);
+ // }
+ // System.out.println("Goodbye" + recur + " - transformed");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAOAoADwAaCgAOABsJABwAHQcAHgoABAAaCAAfCgAEACAKAAQAIQgAIgoABAAjCgAk" +
+ "ACULACYAJwgAKAcAKQcAKgEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUB" +
+ "AAVzYXlIaQEAGChJTGphdmEvbGFuZy9SdW5uYWJsZTspVgEADHByaXZhdGVTYXlIaQEADVN0YWNr" +
+ "TWFwVGFibGUBAApTb3VyY2VGaWxlAQAOVHJhbnNmb3JtLmphdmEMABAAEQwAFgAVBwArDAAsAC0B" +
+ "ABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgEABUhlbGxvDAAuAC8MAC4AMAEADiAtIHRyYW5zZm9y" +
+ "bWVkDAAxADIHADMMADQANQcANgwANwARAQAHR29vZGJ5ZQEACVRyYW5zZm9ybQEAEGphdmEvbGFu" +
+ "Zy9PYmplY3QBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07" +
+ "AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7" +
+ "AQAcKEkpTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nAQAUKClMamF2YS9sYW5n" +
+ "L1N0cmluZzsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0" +
+ "cmluZzspVgEAEmphdmEvbGFuZy9SdW5uYWJsZQEAA3J1bgAgAA4ADwAAAAAAAwAAABAAEQABABIA" +
+ "AAAdAAEAAQAAAAUqtwABsQAAAAEAEwAAAAYAAQAAAAEAAQAUABUAAQASAAAAIwADAAMAAAAHKhss" +
+ "twACsQAAAAEAEwAAAAoAAgAAAAMABgAEAAIAFgAVAAEAEgAAAJ0AAwADAAAAX7IAA7sABFm3AAUS" +
+ "BrYABxu2AAgSCbYAB7YACrYACxsEoAAULLkADAEAKhsEZCy3AAKnAA8bmQALKhsEZCy3AAKyAAO7" +
+ "AARZtwAFEg22AAcbtgAIEgm2AAe2AAq2AAuxAAAAAgATAAAAIgAIAAAABgAeAAcAIwAIACkACQA0" +
+ "AAoAOAALAEAADQBeAA4AFwAAAAQAAjQLAAEAGAAAAAIAGQ==");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQBQqwVIiZvIuS8j1HDurKbXZEV62Mnug5PEBAAAcAAAAHhWNBIAAAAAAAAAACQEAAAb" +
+ "AAAAcAAAAAkAAADcAAAABgAAAAABAAABAAAASAEAAAoAAABQAQAAAQAAAKABAAAEAwAAwAEAAMAC" +
+ "AADQAgAA2AIAAOECAADoAgAA6wIAAO4CAADyAgAA9gIAAAMDAAAaAwAALgMAAEQDAABYAwAAcwMA" +
+ "AIcDAACXAwAAmgMAAJ8DAACjAwAAqwMAAL8DAADEAwAAzQMAANsDAADgAwAA5wMAAAQAAAAIAAAA" +
+ "CQAAAAoAAAALAAAADAAAAA0AAAAOAAAAEAAAAAUAAAAFAAAAAAAAAAYAAAAGAAAAqAIAAAcAAAAG" +
+ "AAAAsAIAABAAAAAIAAAAAAAAABEAAAAIAAAAuAIAABIAAAAIAAAAsAIAAAcAAgAVAAAAAQADAAEA" +
+ "AAABAAQAFwAAAAEABAAZAAAAAgAFABYAAAADAAMAAQAAAAQAAwAYAAAABgADAAEAAAAGAAEAEwAA" +
+ "AAYAAgATAAAABgAAABoAAAABAAAAAAAAAAMAAAAAAAAADwAAAAAAAAAQBAAAAAAAAAEAAQABAAAA" +
+ "8QMAAAQAAABwEAQAAAAOAAYAAwADAAAA9gMAAFQAAABiAAAAIgEGAHAQBgABABsCAwAAAG4gCAAh" +
+ "AAwBbiAHAEEADAEbAgAAAABuIAgAIQAMAW4QCQABAAwBbiADABAAEhAzBCsAchAFAAUA2AAE/3Aw" +
+ "AQADBWIAAAAiAQYAcBAGAAEAGwICAAAAbiAIACEADAFuIAcAQQAMARsCAAAAAG4gCAAhAAwBbhAJ" +
+ "AAEADAFuIAMAEAAOADgE3//YAAT/cDABAAMFKNgDAAMAAwAAAAgEAAAEAAAAcDABABACDgABAAAA" +
+ "AAAAAAEAAAAFAAAAAgAAAAAABAAOIC0gdHJhbnNmb3JtZWQABjxpbml0PgAHR29vZGJ5ZQAFSGVs" +
+ "bG8AAUkAAUwAAkxJAAJMTAALTFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwASTGph" +
+ "dmEvbGFuZy9PYmplY3Q7ABRMamF2YS9sYW5nL1J1bm5hYmxlOwASTGphdmEvbGFuZy9TdHJpbmc7" +
+ "ABlMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7ABJMamF2YS9sYW5nL1N5c3RlbTsADlRyYW5zZm9y" +
+ "bS5qYXZhAAFWAANWSUwAAlZMAAZhcHBlbmQAEmVtaXR0ZXI6IGphY2stNC4yNAADb3V0AAdwcmlu" +
+ "dGxuAAxwcml2YXRlU2F5SGkAA3J1bgAFc2F5SGkACHRvU3RyaW5nAAEABw4ABgIAAAcOASAPPDxd" +
+ "ASAPGS0AAwIAAAcOPAAAAAIBAICABMADAQLYAwIBkAUAAA0AAAAAAAAAAQAAAAAAAAABAAAAGwAA" +
+ "AHAAAAACAAAACQAAANwAAAADAAAABgAAAAABAAAEAAAAAQAAAEgBAAAFAAAACgAAAFABAAAGAAAA" +
+ "AQAAAKABAAABIAAAAwAAAMABAAABEAAAAwAAAKgCAAACIAAAGwAAAMACAAADIAAAAwAAAPEDAAAA" +
+ "IAAAAQAAABAEAAAAEAAAAQAAACQEAAA=");
+
+ public static void main(String[] args) {
+ doTest(new Transform());
+ }
+
+ public static void doTest(Transform t) {
+ t.sayHi(2, () -> { System.out.println("Not doing anything here"); });
+ t.sayHi(2, () -> {
+ System.out.println("transforming calling function");
+ doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ });
+ t.sayHi(2, () -> { System.out.println("Not doing anything here"); });
+ }
+
+ // Transforms the class
+ private static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+}
diff --git a/test/942-private-recursive/src/Transform.java b/test/942-private-recursive/src/Transform.java
new file mode 100644
index 0000000000..7714326066
--- /dev/null
+++ b/test/942-private-recursive/src/Transform.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class Transform {
+ private void privateSayHi(int recur, Runnable r) {
+ System.out.println("hello" + recur);
+ if (recur == 1) {
+ r.run();
+ privateSayHi(recur - 1, r);
+ } else if (recur != 0) {
+ privateSayHi(recur - 1, r);
+ }
+ System.out.println("goodbye" + recur);
+ }
+
+ public void sayHi(int recur, Runnable r) {
+ privateSayHi(recur, r);
+ }
+}
diff --git a/test/943-private-recursive-jit/build b/test/943-private-recursive-jit/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/943-private-recursive-jit/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/943-private-recursive-jit/expected.txt b/test/943-private-recursive-jit/expected.txt
new file mode 100644
index 0000000000..447f4a2245
--- /dev/null
+++ b/test/943-private-recursive-jit/expected.txt
@@ -0,0 +1,22 @@
+hello2
+hello1
+Not doing anything here
+hello0
+goodbye0
+goodbye1
+goodbye2
+hello2
+hello1
+transforming calling function
+hello0 - transformed
+goodbye0 - transformed
+goodbye1
+goodbye2
+hello2 - transformed
+hello1 - transformed
+Not doing anything here
+hello0 - transformed
+goodbye0 - transformed
+goodbye1 - transformed
+goodbye2 - transformed
+
diff --git a/test/943-private-recursive-jit/info.txt b/test/943-private-recursive-jit/info.txt
new file mode 100644
index 0000000000..c8b892cedd
--- /dev/null
+++ b/test/943-private-recursive-jit/info.txt
@@ -0,0 +1 @@
+Tests basic obsolete method support
diff --git a/test/943-private-recursive-jit/run b/test/943-private-recursive-jit/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/943-private-recursive-jit/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/943-private-recursive-jit/src/Main.java b/test/943-private-recursive-jit/src/Main.java
new file mode 100644
index 0000000000..8fa534d997
--- /dev/null
+++ b/test/943-private-recursive-jit/src/Main.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016 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.util.Base64;
+import java.util.function.Consumer;
+import java.lang.reflect.Method;
+
+public class Main {
+ static final boolean ALWAYS_PRINT = false;
+
+ // import java.util.function.Consumer;
+ // class Transform {
+ // public void sayHi(int recur, Consumer<String> reporter, Runnable r) {
+ // privateSayHi(recur, reporter, r);
+ // }
+ // private void privateSayHi(int recur, Consumer<String> reporter, Runnable r) {
+ // reporter.accpet("hello" + recur + " - transformed");
+ // if (recur == 1) {
+ // r.run();
+ // privateSayHi(recur - 1, reporter, r);
+ // } else if (recur != 0) {
+ // privateSayHi(recur - 1, reporter, r);
+ // }
+ // reporter.accept("goodbye" + recur + " - transformed");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQANAoADgAbCgANABwHAB0KAAMAGwgAHgoAAwAfCgADACAIACEKAAMAIgsAIwAkCwAl" +
+ "ACYIACcHACgHACkBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFc2F5" +
+ "SGkBADUoSUxqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7TGphdmEvbGFuZy9SdW5uYWJsZTsp" +
+ "VgEACVNpZ25hdHVyZQEASShJTGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjxMamF2YS9sYW5n" +
+ "L1N0cmluZzs+O0xqYXZhL2xhbmcvUnVubmFibGU7KVYBAAxwcml2YXRlU2F5SGkBAA1TdGFja01h" +
+ "cFRhYmxlAQAKU291cmNlRmlsZQEADlRyYW5zZm9ybS5qYXZhDAAPABAMABcAFAEAF2phdmEvbGFu" +
+ "Zy9TdHJpbmdCdWlsZGVyAQAFaGVsbG8MACoAKwwAKgAsAQAOIC0gdHJhbnNmb3JtZWQMAC0ALgcA" +
+ "LwwAMAAxBwAyDAAzABABAAdnb29kYnllAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAEA" +
+ "BmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEA" +
+ "HChJKUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9T" +
+ "dHJpbmc7AQAbamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAQAGYWNjZXB0AQAVKExqYXZhL2xh" +
+ "bmcvT2JqZWN0OylWAQASamF2YS9sYW5nL1J1bm5hYmxlAQADcnVuACAADQAOAAAAAAADAAAADwAQ" +
+ "AAEAEQAAAB0AAQABAAAABSq3AAGxAAAAAQASAAAABgABAAAAAgABABMAFAACABEAAAAkAAQABAAA" +
+ "AAgqGywttwACsQAAAAEAEgAAAAoAAgAAAAQABwAFABUAAAACABYAAgAXABQAAgARAAAAnwAEAAQA" +
+ "AABhLLsAA1m3AAQSBbYABhu2AAcSCLYABrYACbkACgIAGwSgABUtuQALAQAqGwRkLC23AAKnABAb" +
+ "mQAMKhsEZCwttwACLLsAA1m3AAQSDLYABhu2AAcSCLYABrYACbkACgIAsQAAAAIAEgAAACIACAAA" +
+ "AAcAHgAIACMACQApAAoANQALADkADABCAA4AYAAPABgAAAAEAAI1DAAVAAAAAgAWAAEAGQAAAAIA" +
+ "Gg==");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQCevtlr8B0kh/duuDYqXkGz/w9lMmtCCuRoBQAAcAAAAHhWNBIAAAAAAAAAALAEAAAg" +
+ "AAAAcAAAAAkAAADwAAAABgAAABQBAAAAAAAAAAAAAAoAAABcAQAAAQAAAKwBAACcAwAAzAEAAPYC" +
+ "AAAGAwAACgMAAA4DAAARAwAAGQMAAB0DAAAgAwAAIwMAACcDAAArAwAAOAMAAFcDAABrAwAAgQMA" +
+ "AJUDAACwAwAAzgMAAO0DAAD9AwAAAAQAAAYEAAAKBAAAEgQAABoEAAAuBAAANwQAAD4EAABMBAAA" +
+ "UQQAAFgEAABiBAAABgAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABEAAAATAAAABwAAAAUAAAAA" +
+ "AAAACAAAAAYAAADUAgAACQAAAAYAAADcAgAAEwAAAAgAAAAAAAAAFAAAAAgAAADkAgAAFQAAAAgA" +
+ "AADwAgAAAQADAAQAAAABAAQAGwAAAAEABAAdAAAAAwADAAQAAAAEAAMAHAAAAAYAAwAEAAAABgAB" +
+ "ABcAAAAGAAIAFwAAAAYAAAAeAAAABwAFABYAAAABAAAAAAAAAAMAAAAAAAAAEgAAALQCAACeBAAA" +
+ "AAAAAAEAAACKBAAAAQABAAEAAABpBAAABAAAAHAQAwAAAA4ABgAEAAQAAABuBAAAUAAAACIABgBw" +
+ "EAUAAAAbARoAAABuIAcAEAAMAG4gBgAwAAwAGwEAAAAAbiAHABAADABuEAgAAAAMAHIgCQAEABIQ" +
+ "MwMpAHIQBAAFANgAA/9wQAEAAlQiAAYAcBAFAAAAGwEZAAAAbiAHABAADABuIAYAMAAMABsBAAAA" +
+ "AG4gBwAQAAwAbhAIAAAADAByIAkABAAOADgD4f/YAAP/cEABAAJUKNoEAAQABAAAAIEEAAAEAAAA" +
+ "cEABABAyDgAAAAAAAAAAAAIAAAAAAAAAAQAAAMwBAAACAAAAzAEAAAEAAAAAAAAAAQAAAAUAAAAD" +
+ "AAAAAAAHAAQAAAABAAAAAwAOIC0gdHJhbnNmb3JtZWQAAihJAAIpVgABPAAGPGluaXQ+AAI+OwAB" +
+ "SQABTAACTEkAAkxMAAtMVHJhbnNmb3JtOwAdTGRhbHZpay9hbm5vdGF0aW9uL1NpZ25hdHVyZTsA" +
+ "EkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEvbGFuZy9SdW5uYWJsZTsAEkxqYXZhL2xhbmcvU3Ry" +
+ "aW5nOwAZTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwAcTGphdmEvdXRpbC9mdW5jdGlvbi9Db25z" +
+ "dW1lcgAdTGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjsADlRyYW5zZm9ybS5qYXZhAAFWAARW" +
+ "SUxMAAJWTAAGYWNjZXB0AAZhcHBlbmQAEmVtaXR0ZXI6IGphY2stNC4yNAAHZ29vZGJ5ZQAFaGVs" +
+ "bG8ADHByaXZhdGVTYXlIaQADcnVuAAVzYXlIaQAIdG9TdHJpbmcABXZhbHVlAAIABw4ABwMAAAAH" +
+ "DgEeDzw8XQEeDxktAAQDAAAABw48AAICAR8cBxcBFxAXAxcOFwUXDRcCAAACAQCAgATUAwEC7AMC" +
+ "AZwFDwAAAAAAAAABAAAAAAAAAAEAAAAgAAAAcAAAAAIAAAAJAAAA8AAAAAMAAAAGAAAAFAEAAAUA" +
+ "AAAKAAAAXAEAAAYAAAABAAAArAEAAAMQAAABAAAAzAEAAAEgAAADAAAA1AEAAAYgAAABAAAAtAIA" +
+ "AAEQAAAEAAAA1AIAAAIgAAAgAAAA9gIAAAMgAAADAAAAaQQAAAQgAAABAAAAigQAAAAgAAABAAAA" +
+ "ngQAAAAQAAABAAAAsAQAAA==");
+
+ // A class that we can use to keep track of the output of this test.
+ private static class TestWatcher implements Consumer<String> {
+ private StringBuilder sb;
+ public TestWatcher() {
+ sb = new StringBuilder();
+ }
+
+ @Override
+ public void accept(String s) {
+ if (Main.ALWAYS_PRINT) {
+ System.out.println(s);
+ }
+ sb.append(s);
+ sb.append('\n');
+ }
+
+ public String getOutput() {
+ return sb.toString();
+ }
+
+ public void clear() {
+ sb = new StringBuilder();
+ }
+ }
+
+ public static void main(String[] args) {
+ doTest(new Transform());
+ }
+
+ private static boolean retry = false;
+
+ public static void doTest(Transform t) {
+ final TestWatcher reporter = new TestWatcher();
+ Method say_hi_method;
+ Method private_say_hi_method;
+ // Figure out if we can even JIT at all.
+ final boolean has_jit = hasJit();
+ try {
+ say_hi_method = Transform.class.getDeclaredMethod(
+ "sayHi", int.class, Consumer.class, Runnable.class);
+ private_say_hi_method = Transform.class.getDeclaredMethod(
+ "privateSayHi", int.class, Consumer.class, Runnable.class);
+ } catch (Exception e) {
+ System.out.println("Unable to find methods!");
+ e.printStackTrace();
+ return;
+ }
+ // Makes sure the stack is the way we want it for the test and does the redefinition. It will
+ // set the retry boolean to true if we need to go around again due to jit code being GCd.
+ Runnable do_redefinition = () -> {
+ if (has_jit &&
+ (Main.isInterpretedFunction(say_hi_method, true) ||
+ Main.isInterpretedFunction(private_say_hi_method, true))) {
+ // Try again. We are not running the right jitted methods/cannot redefine them now.
+ retry = true;
+ } else {
+ // Actually do the redefinition. The stack looks good.
+ retry = false;
+ reporter.accept("transforming calling function");
+ doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ }
+ };
+ do {
+ // Run ensureJitCompiled here since it might get GCd
+ ensureJitCompiled(Transform.class, "sayHi");
+ ensureJitCompiled(Transform.class, "privateSayHi");
+ // Clear output.
+ reporter.clear();
+ t.sayHi(2, reporter, () -> { reporter.accept("Not doing anything here"); });
+ t.sayHi(2, reporter, do_redefinition);
+ t.sayHi(2, reporter, () -> { reporter.accept("Not doing anything here"); });
+ } while(retry);
+ System.out.println(reporter.getOutput());
+ }
+
+ private static native boolean hasJit();
+
+ private static native boolean isInterpretedFunction(Method m, boolean require_deoptimizable);
+
+ private static native void ensureJitCompiled(Class c, String name);
+
+ // Transforms the class
+ private static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+}
diff --git a/test/943-private-recursive-jit/src/Transform.java b/test/943-private-recursive-jit/src/Transform.java
new file mode 100644
index 0000000000..9ec3e42544
--- /dev/null
+++ b/test/943-private-recursive-jit/src/Transform.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 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.util.function.Consumer;
+class Transform {
+ public void sayHi(int recur, Consumer<String> reporter, Runnable r) {
+ privateSayHi(recur, reporter, r);
+ }
+
+ private void privateSayHi(int recur, Consumer<String> reporter, Runnable r) {
+ reporter.accept("hello" + recur);
+ if (recur == 1) {
+ r.run();
+ privateSayHi(recur - 1, reporter, r);
+ } else if (recur != 0) {
+ privateSayHi(recur - 1, reporter, r);
+ }
+ reporter.accept("goodbye" + recur);
+ }
+}
diff --git a/test/944-transform-classloaders/build b/test/944-transform-classloaders/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/944-transform-classloaders/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/944-transform-classloaders/classloader.cc b/test/944-transform-classloaders/classloader.cc
new file mode 100644
index 0000000000..5fbd8e11c9
--- /dev/null
+++ b/test/944-transform-classloaders/classloader.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "base/macros.h"
+#include "jni.h"
+#include "mirror/class-inl.h"
+#include "openjdkjvmti/jvmti.h"
+#include "ScopedLocalRef.h"
+
+#include "ti-agent/common_helper.h"
+#include "ti-agent/common_load.h"
+
+namespace art {
+namespace Test944TransformClassloaders {
+
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_getDexFilePointer(JNIEnv* env, jclass, jclass klass) {
+ if (Runtime::Current() == nullptr) {
+ env->ThrowNew(env->FindClass("java/lang/Exception"),
+ "We do not seem to be running in ART! Unable to get dex file.");
+ return 0;
+ }
+ ScopedObjectAccess soa(env);
+ // This sequence of casts must be the same as those done in
+ // runtime/native/dalvik_system_DexFile.cc in order to ensure that we get the same results.
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(
+ &soa.Decode<mirror::Class>(klass)->GetDexFile()));
+}
+
+} // namespace Test944TransformClassloaders
+} // namespace art
diff --git a/test/944-transform-classloaders/expected.txt b/test/944-transform-classloaders/expected.txt
new file mode 100644
index 0000000000..79522479dd
--- /dev/null
+++ b/test/944-transform-classloaders/expected.txt
@@ -0,0 +1,5 @@
+hello
+hello2
+Goodbye
+Goodbye2
+Passed
diff --git a/test/944-transform-classloaders/info.txt b/test/944-transform-classloaders/info.txt
new file mode 100644
index 0000000000..9155564d62
--- /dev/null
+++ b/test/944-transform-classloaders/info.txt
@@ -0,0 +1,7 @@
+Tests that redefined dex files are stored in the appropriate classloader.
+
+This test cannot run on the RI.
+
+We use reflection with setAccessible(true) to examine the private internals of
+classloaders. Changes to the internal operation or definition of
+dalvik.system.BaseDexClassLoader might cause this test to fail.
diff --git a/test/944-transform-classloaders/run b/test/944-transform-classloaders/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/944-transform-classloaders/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/944-transform-classloaders/src/CommonClassDefinition.java b/test/944-transform-classloaders/src/CommonClassDefinition.java
new file mode 100644
index 0000000000..62602a02e9
--- /dev/null
+++ b/test/944-transform-classloaders/src/CommonClassDefinition.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+class CommonClassDefinition {
+ public final Class<?> target;
+ public final byte[] class_file_bytes;
+ public final byte[] dex_file_bytes;
+
+ CommonClassDefinition(Class<?> target, byte[] class_file_bytes, byte[] dex_file_bytes) {
+ this.target = target;
+ this.class_file_bytes = class_file_bytes;
+ this.dex_file_bytes = dex_file_bytes;
+ }
+}
diff --git a/test/944-transform-classloaders/src/Main.java b/test/944-transform-classloaders/src/Main.java
new file mode 100644
index 0000000000..4911e00a70
--- /dev/null
+++ b/test/944-transform-classloaders/src/Main.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2017 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.util.Arrays;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.lang.reflect.*;
+public class Main {
+
+ /**
+ * base64 encoded class/dex file for
+ * class Transform {
+ * public void sayHi() {
+ * System.out.println("Goodbye");
+ * }
+ * }
+ */
+ private static CommonClassDefinition TRANSFORM_DEFINITION = new CommonClassDefinition(
+ Transform.class,
+ Base64.getDecoder().decode(
+ "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUB" +
+ "AA9MaW5lTnVtYmVyVGFibGUBAAVzYXlIaQEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwA" +
+ "BwAIBwAWDAAXABgBAAdHb29kYnllBwAZDAAaABsBAAlUcmFuc2Zvcm0BABBqYXZhL2xhbmcvT2Jq" +
+ "ZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2ph" +
+ "dmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACAABQAG" +
+ "AAAAAAACAAAABwAIAAEACQAAAB0AAQABAAAABSq3AAGxAAAAAQAKAAAABgABAAAAEQABAAsACAAB" +
+ "AAkAAAAlAAIAAQAAAAmyAAISA7YABLEAAAABAAoAAAAKAAIAAAATAAgAFAABAAwAAAACAA0="),
+ Base64.getDecoder().decode(
+ "ZGV4CjAzNQCLXSBQ5FiS3f16krSYZFF8xYZtFVp0GRXMAgAAcAAAAHhWNBIAAAAAAAAAACwCAAAO" +
+ "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACsAQAAIAEAAGIB" +
+ "AABqAQAAcwEAAIABAACXAQAAqwEAAL8BAADTAQAA4wEAAOYBAADqAQAA/gEAAAMCAAAMAgAAAgAA" +
+ "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" +
+ "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAAB4CAAAA" +
+ "AAAAAQABAAEAAAATAgAABAAAAHAQAwAAAA4AAwABAAIAAAAYAgAACQAAAGIAAAAbAQEAAABuIAIA" +
+ "EAAOAAAAAQAAAAMABjxpbml0PgAHR29vZGJ5ZQALTFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50" +
+ "U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xh" +
+ "bmcvU3lzdGVtOwAOVHJhbnNmb3JtLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTMuMzYAA291" +
+ "dAAHcHJpbnRsbgAFc2F5SGkAEQAHDgATAAcOhQAAAAEBAICABKACAQG4Ag0AAAAAAAAAAQAAAAAA" +
+ "AAABAAAADgAAAHAAAAACAAAABgAAAKgAAAADAAAAAgAAAMAAAAAEAAAAAQAAANgAAAAFAAAABAAA" +
+ "AOAAAAAGAAAAAQAAAAABAAABIAAAAgAAACABAAABEAAAAQAAAFwBAAACIAAADgAAAGIBAAADIAAA" +
+ "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA="));
+
+ /**
+ * base64 encoded class/dex file for
+ * class Transform2 {
+ * public void sayHi() {
+ * System.out.println("Goodbye2");
+ * }
+ * }
+ */
+ private static CommonClassDefinition TRANSFORM2_DEFINITION = new CommonClassDefinition(
+ Transform2.class,
+ Base64.getDecoder().decode(
+ "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUB" +
+ "AA9MaW5lTnVtYmVyVGFibGUBAAVzYXlIaQEAClNvdXJjZUZpbGUBAA9UcmFuc2Zvcm0yLmphdmEM" +
+ "AAcACAcAFgwAFwAYAQAIR29vZGJ5ZTIHABkMABoAGwEAClRyYW5zZm9ybTIBABBqYXZhL2xhbmcv" +
+ "T2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEA" +
+ "E2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACAA" +
+ "BQAGAAAAAAACAAAABwAIAAEACQAAAB0AAQABAAAABSq3AAGxAAAAAQAKAAAABgABAAAAAQABAAsA" +
+ "CAABAAkAAAAlAAIAAQAAAAmyAAISA7YABLEAAAABAAoAAAAKAAIAAAADAAgABAABAAwAAAACAA0="),
+ Base64.getDecoder().decode(
+ "ZGV4CjAzNQABX6vL8OT7aGLjbzFBEfCM9Aaz+zzGzVnQAgAAcAAAAHhWNBIAAAAAAAAAADACAAAO" +
+ "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACwAQAAIAEAAGIB" +
+ "AABqAQAAdAEAAIIBAACZAQAArQEAAMEBAADVAQAA5gEAAOkBAADtAQAAAQIAAAYCAAAPAgAAAgAA" +
+ "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" +
+ "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAACECAAAA" +
+ "AAAAAQABAAEAAAAWAgAABAAAAHAQAwAAAA4AAwABAAIAAAAbAgAACQAAAGIAAAAbAQEAAABuIAIA" +
+ "EAAOAAAAAQAAAAMABjxpbml0PgAIR29vZGJ5ZTIADExUcmFuc2Zvcm0yOwAVTGphdmEvaW8vUHJp" +
+ "bnRTdHJlYW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEv" +
+ "bGFuZy9TeXN0ZW07AA9UcmFuc2Zvcm0yLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTQuMjQA" +
+ "A291dAAHcHJpbnRsbgAFc2F5SGkAAQAHDgADAAcOhwAAAAEBAICABKACAQG4AgANAAAAAAAAAAEA" +
+ "AAAAAAAAAQAAAA4AAABwAAAAAgAAAAYAAACoAAAAAwAAAAIAAADAAAAABAAAAAEAAADYAAAABQAA" +
+ "AAQAAADgAAAABgAAAAEAAAAAAQAAASAAAAIAAAAgAQAAARAAAAEAAABcAQAAAiAAAA4AAABiAQAA" +
+ "AyAAAAIAAAAWAgAAACAAAAEAAAAhAgAAABAAAAEAAAAwAgAA"));
+
+ public static void main(String[] args) throws Exception {
+ doTest();
+ System.out.println("Passed");
+ }
+
+ private static void checkIsInstance(Class<?> klass, Object o) throws Exception {
+ if (!klass.isInstance(o)) {
+ throw new Exception(klass + " is not the class of " + o);
+ }
+ }
+
+ private static boolean arrayContains(long[] arr, long value) {
+ if (arr == null) {
+ return false;
+ }
+ for (int i = 0; i < arr.length; i++) {
+ if (arr[i] == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks that we can find the dex-file for the given class in its classloader.
+ *
+ * Throws if it fails.
+ */
+ private static void checkDexFileInClassLoader(Class<?> klass) throws Exception {
+ // If all the android BCP classes were availible when compiling this test and access checks
+ // weren't a thing this function would be written as follows:
+ //
+ // long dexFilePtr = getDexFilePointer(klass);
+ // dalvik.system.BaseDexClassLoader loader =
+ // (dalvik.system.BaseDexClassLoader)klass.getClassLoader();
+ // dalvik.system.DexPathList pathListValue = loader.pathList;
+ // dalvik.system.DexPathList.Element[] elementArrayValue = pathListValue.dexElements;
+ // int array_length = elementArrayValue.length;
+ // for (int i = 0; i < array_length; i++) {
+ // dalvik.system.DexPathList.Element curElement = elementArrayValue[i];
+ // dalvik.system.DexFile curDexFile = curElement.dexFile;
+ // if (curDexFile == null) {
+ // continue;
+ // }
+ // long[] curCookie = (long[])curDexFile.mCookie;
+ // long[] curInternalCookie = (long[])curDexFile.mInternalCookie;
+ // if (arrayContains(curCookie, dexFilePtr) || arrayContains(curInternalCookie, dexFilePtr)) {
+ // return;
+ // }
+ // }
+ // throw new Exception(
+ // "Unable to find dex file pointer " + dexFilePtr + " in class loader for " + klass);
+
+ // Get all the fields and classes we need by reflection.
+ Class<?> baseDexClassLoaderClass = Class.forName("dalvik.system.BaseDexClassLoader");
+ Field pathListField = baseDexClassLoaderClass.getDeclaredField("pathList");
+
+ Class<?> dexPathListClass = Class.forName("dalvik.system.DexPathList");
+ Field elementArrayField = dexPathListClass.getDeclaredField("dexElements");
+
+ Class<?> dexPathListElementClass = Class.forName("dalvik.system.DexPathList$Element");
+ Field dexFileField = dexPathListElementClass.getDeclaredField("dexFile");
+
+ Class<?> dexFileClass = Class.forName("dalvik.system.DexFile");
+ Field dexFileCookieField = dexFileClass.getDeclaredField("mCookie");
+ Field dexFileInternalCookieField = dexFileClass.getDeclaredField("mInternalCookie");
+
+ // Make all the fields accessible
+ AccessibleObject.setAccessible(new AccessibleObject[] { pathListField,
+ elementArrayField,
+ dexFileField,
+ dexFileCookieField,
+ dexFileInternalCookieField }, true);
+
+ long dexFilePtr = getDexFilePointer(klass);
+
+ ClassLoader loader = klass.getClassLoader();
+ checkIsInstance(baseDexClassLoaderClass, loader);
+ // DexPathList pathListValue = ((BaseDexClassLoader) loader).pathList;
+ Object pathListValue = pathListField.get(loader);
+
+ checkIsInstance(dexPathListClass, pathListValue);
+
+ // DexPathList.Element[] elementArrayValue = pathListValue.dexElements;
+ Object elementArrayValue = elementArrayField.get(pathListValue);
+ if (!elementArrayValue.getClass().isArray() ||
+ elementArrayValue.getClass().getComponentType() != dexPathListElementClass) {
+ throw new Exception("elementArrayValue is not an " + dexPathListElementClass + " array!");
+ }
+ // int array_length = elementArrayValue.length;
+ int array_length = Array.getLength(elementArrayValue);
+ for (int i = 0; i < array_length; i++) {
+ // DexPathList.Element curElement = elementArrayValue[i];
+ Object curElement = Array.get(elementArrayValue, i);
+ checkIsInstance(dexPathListElementClass, curElement);
+
+ // DexFile curDexFile = curElement.dexFile;
+ Object curDexFile = dexFileField.get(curElement);
+ if (curDexFile == null) {
+ continue;
+ }
+ checkIsInstance(dexFileClass, curDexFile);
+
+ // long[] curCookie = (long[])curDexFile.mCookie;
+ long[] curCookie = (long[])dexFileCookieField.get(curDexFile);
+ // long[] curInternalCookie = (long[])curDexFile.mInternalCookie;
+ long[] curInternalCookie = (long[])dexFileInternalCookieField.get(curDexFile);
+
+ if (arrayContains(curCookie, dexFilePtr) || arrayContains(curInternalCookie, dexFilePtr)) {
+ return;
+ }
+ }
+ throw new Exception(
+ "Unable to find dex file pointer " + dexFilePtr + " in class loader for " + klass);
+ }
+
+ private static void doTest() throws Exception {
+ Transform t = new Transform();
+ Transform2 t2 = new Transform2();
+
+ long initial_t1_dex = getDexFilePointer(Transform.class);
+ long initial_t2_dex = getDexFilePointer(Transform2.class);
+ if (initial_t2_dex != initial_t1_dex) {
+ throw new Exception("The classes " + Transform.class + " and " + Transform2.class + " " +
+ "have different initial dex files!");
+ }
+ checkDexFileInClassLoader(Transform.class);
+ checkDexFileInClassLoader(Transform2.class);
+
+ // Make sure they are loaded
+ t.sayHi();
+ t2.sayHi();
+ // Redefine both of the classes.
+ doMultiClassRedefinition(TRANSFORM_DEFINITION, TRANSFORM2_DEFINITION);
+ // Make sure we actually transformed them!
+ t.sayHi();
+ t2.sayHi();
+
+ long final_t1_dex = getDexFilePointer(Transform.class);
+ long final_t2_dex = getDexFilePointer(Transform2.class);
+ if (final_t2_dex == final_t1_dex) {
+ throw new Exception("The classes " + Transform.class + " and " + Transform2.class + " " +
+ "have the same initial dex files!");
+ } else if (final_t1_dex == initial_t1_dex) {
+ throw new Exception("The class " + Transform.class + " did not get a new dex file!");
+ } else if (final_t2_dex == initial_t2_dex) {
+ throw new Exception("The class " + Transform2.class + " did not get a new dex file!");
+ }
+ // Check to make sure the new dex files are in the class loader.
+ checkDexFileInClassLoader(Transform.class);
+ checkDexFileInClassLoader(Transform2.class);
+ }
+
+ private static void doMultiClassRedefinition(CommonClassDefinition... defs) {
+ ArrayList<Class<?>> classes = new ArrayList<>();
+ ArrayList<byte[]> class_files = new ArrayList<>();
+ ArrayList<byte[]> dex_files = new ArrayList<>();
+
+ for (CommonClassDefinition d : defs) {
+ classes.add(d.target);
+ class_files.add(d.class_file_bytes);
+ dex_files.add(d.dex_file_bytes);
+ }
+ doCommonMultiClassRedefinition(classes.toArray(new Class<?>[0]),
+ class_files.toArray(new byte[0][]),
+ dex_files.toArray(new byte[0][]));
+ }
+
+ // Gets the 'long' (really a native pointer) that is stored in the ClassLoader representing the
+ // DexFile a class is loaded from. This is converted from the DexFile* in the same way it is done
+ // in runtime/native/dalvik_system_DexFile.cc
+ private static native long getDexFilePointer(Class<?> target);
+ // Transforms the classes
+ private static native void doCommonMultiClassRedefinition(Class<?>[] targets,
+ byte[][] classfiles,
+ byte[][] dexfiles);
+}
diff --git a/test/944-transform-classloaders/src/Transform.java b/test/944-transform-classloaders/src/Transform.java
new file mode 100644
index 0000000000..8e8af355da
--- /dev/null
+++ b/test/944-transform-classloaders/src/Transform.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class Transform {
+ public void sayHi() {
+ // Use lower 'h' to make sure the string will have a different string id
+ // than the transformation (the transformation code is the same except
+ // the actual printed String, which was making the test inacurately passing
+ // in JIT mode when loading the string from the dex cache, as the string ids
+ // of the two different strings were the same).
+ // We know the string ids will be different because lexicographically:
+ // "Goodbye" < "LTransform;" < "hello".
+ System.out.println("hello");
+ }
+}
diff --git a/test/944-transform-classloaders/src/Transform2.java b/test/944-transform-classloaders/src/Transform2.java
new file mode 100644
index 0000000000..eb22842184
--- /dev/null
+++ b/test/944-transform-classloaders/src/Transform2.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class Transform2 {
+ public void sayHi() {
+ System.out.println("hello2");
+ }
+}
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index f8daba6239..fc9f030559 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -15,6 +15,7 @@
*/
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
@@ -77,6 +78,7 @@ public class Main {
testReturnValueConversions();
testVariableArity();
testVariableArity_MethodHandles_bind();
+ testRevealDirect();
}
public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
@@ -384,6 +386,10 @@ public class Main {
public String publicMethod() {
return "publicMethod";
}
+
+ public String publicVarArgsMethod(String... args) {
+ return "publicVarArgsMethod";
+ }
}
public static void testUnreflects() throws Throwable {
@@ -670,6 +676,13 @@ public class Main {
Integer.class, MethodType.methodType(Integer.class, Integer.class));
fail("Unexpected success for non-void type for findConstructor");
} catch (NoSuchMethodException e) {}
+
+ // Array class constructor.
+ try {
+ MethodHandle foo = MethodHandles.lookup().findConstructor(
+ Object[].class, MethodType.methodType(void.class));
+ fail("Unexpected success for array class type for findConstructor");
+ } catch (NoSuchMethodException e) {}
}
public static void testStringConstructors() throws Throwable {
@@ -1486,4 +1499,117 @@ public class Main {
fail();
} catch (WrongMethodTypeException e) {}
}
+
+ public static void testRevealDirect() throws Throwable {
+ // Test with a virtual method :
+ MethodType type = MethodType.methodType(String.class);
+ MethodHandle handle = MethodHandles.lookup().findVirtual(
+ UnreflectTester.class, "publicMethod", type);
+
+ // Comparisons with an equivalent member obtained via reflection :
+ MethodHandleInfo info = MethodHandles.lookup().revealDirect(handle);
+ Method meth = UnreflectTester.class.getMethod("publicMethod");
+
+ assertEquals(MethodHandleInfo.REF_invokeVirtual, info.getReferenceKind());
+ assertEquals("publicMethod", info.getName());
+ assertTrue(UnreflectTester.class == info.getDeclaringClass());
+ assertFalse(info.isVarArgs());
+ assertEquals(meth, info.reflectAs(Method.class, MethodHandles.lookup()));
+ assertEquals(type, info.getMethodType());
+
+ // Resolution via a public lookup should fail because the method in question
+ // isn't public.
+ try {
+ info.reflectAs(Method.class, MethodHandles.publicLookup());
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // Test with a static method :
+ handle = MethodHandles.lookup().findStatic(UnreflectTester.class,
+ "publicStaticMethod",
+ MethodType.methodType(String.class));
+
+ info = MethodHandles.lookup().revealDirect(handle);
+ meth = UnreflectTester.class.getMethod("publicStaticMethod");
+ assertEquals(MethodHandleInfo.REF_invokeStatic, info.getReferenceKind());
+ assertEquals("publicStaticMethod", info.getName());
+ assertTrue(UnreflectTester.class == info.getDeclaringClass());
+ assertFalse(info.isVarArgs());
+ assertEquals(meth, info.reflectAs(Method.class, MethodHandles.lookup()));
+ assertEquals(type, info.getMethodType());
+
+ // Test with a var-args method :
+ type = MethodType.methodType(String.class, String[].class);
+ handle = MethodHandles.lookup().findVirtual(UnreflectTester.class,
+ "publicVarArgsMethod", type);
+
+ info = MethodHandles.lookup().revealDirect(handle);
+ meth = UnreflectTester.class.getMethod("publicVarArgsMethod", String[].class);
+ assertEquals(MethodHandleInfo.REF_invokeVirtual, info.getReferenceKind());
+ assertEquals("publicVarArgsMethod", info.getName());
+ assertTrue(UnreflectTester.class == info.getDeclaringClass());
+ assertTrue(info.isVarArgs());
+ assertEquals(meth, info.reflectAs(Method.class, MethodHandles.lookup()));
+ assertEquals(type, info.getMethodType());
+
+ // Test with a constructor :
+ Constructor cons = UnreflectTester.class.getConstructor(String.class, boolean.class);
+ type = MethodType.methodType(void.class, String.class, boolean.class);
+ handle = MethodHandles.lookup().findConstructor(UnreflectTester.class, type);
+
+ info = MethodHandles.lookup().revealDirect(handle);
+ assertEquals(MethodHandleInfo.REF_newInvokeSpecial, info.getReferenceKind());
+ assertEquals("<init>", info.getName());
+ assertTrue(UnreflectTester.class == info.getDeclaringClass());
+ assertFalse(info.isVarArgs());
+ assertEquals(cons, info.reflectAs(Constructor.class, MethodHandles.lookup()));
+ assertEquals(type, info.getMethodType());
+
+ // Test with a static field :
+ Field field = UnreflectTester.class.getField("publicStaticField");
+
+ handle = MethodHandles.lookup().findStaticSetter(
+ UnreflectTester.class, "publicStaticField", String.class);
+
+ info = MethodHandles.lookup().revealDirect(handle);
+ assertEquals(MethodHandleInfo.REF_putStatic, info.getReferenceKind());
+ assertEquals("publicStaticField", info.getName());
+ assertTrue(UnreflectTester.class == info.getDeclaringClass());
+ assertFalse(info.isVarArgs());
+ assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup()));
+ assertEquals(MethodType.methodType(void.class, String.class), info.getMethodType());
+
+ // Test with a setter on the same field, the type of the handle should change
+ // but everything else must remain the same.
+ handle = MethodHandles.lookup().findStaticGetter(
+ UnreflectTester.class, "publicStaticField", String.class);
+ info = MethodHandles.lookup().revealDirect(handle);
+ assertEquals(MethodHandleInfo.REF_getStatic, info.getReferenceKind());
+ assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup()));
+ assertEquals(MethodType.methodType(String.class), info.getMethodType());
+
+ // Test with an instance field :
+ field = UnreflectTester.class.getField("publicField");
+
+ handle = MethodHandles.lookup().findSetter(
+ UnreflectTester.class, "publicField", String.class);
+
+ info = MethodHandles.lookup().revealDirect(handle);
+ assertEquals(MethodHandleInfo.REF_putField, info.getReferenceKind());
+ assertEquals("publicField", info.getName());
+ assertTrue(UnreflectTester.class == info.getDeclaringClass());
+ assertFalse(info.isVarArgs());
+ assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup()));
+ assertEquals(MethodType.methodType(void.class, String.class), info.getMethodType());
+
+ // Test with a setter on the same field, the type of the handle should change
+ // but everything else must remain the same.
+ handle = MethodHandles.lookup().findGetter(
+ UnreflectTester.class, "publicField", String.class);
+ info = MethodHandles.lookup().revealDirect(handle);
+ assertEquals(MethodHandleInfo.REF_getField, info.getReferenceKind());
+ assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup()));
+ assertEquals(MethodType.methodType(String.class), info.getMethodType());
+ }
}
diff --git a/test/957-methodhandle-transforms/expected.txt b/test/957-methodhandle-transforms/expected.txt
index 154051f847..cf6b5a14b5 100644
--- a/test/957-methodhandle-transforms/expected.txt
+++ b/test/957-methodhandle-transforms/expected.txt
@@ -47,3 +47,32 @@ a: a, b:1.0, c: 2.0, d: 3.0
a: a, b:1.0, c: 2.0, d: 3.0
a: a, b:1.0, c: 2.0
a: a, b:1.0, c: 2.0
+a: a, b:b, c: c
+a: a, b:b, c: c
+a: a, b:43
+a: a, b:b, c: c
+a: a, b:true, c: false
+a: a, b:1, c: 2
+a: a, b:a, c: b
+a: a, b:3, c: 4
+a: a, b:42, c: 43
+a: a, b:100, c: 99
+a: a, b:8.9, c: 9.1
+a: a, b:6.7, c: 7.8
+a: a, b: b, c:c, d:d
+a: a, b: b, c:c, d:d
+a: a, b: b, c:c, d:d
+a: a+b, b: c, c: d
+a: a, b: b+c, c: d
+a: a, b: b, c: c+d
+voidFilter
+a: a, b: b, c: c
+voidFilter
+a: a, b: b, c: c
+a: foo, b:45, c:56, d:bar
+a: foo, b:56, c:57, d:bar
+a: foo, b:56, c:57, d:bar
+a: foo, b:45, c:46, d:bar
+a: c+d ,b:c ,c:d ,d:e
+c+d
+a: a ,b:c ,c:d ,d:e
diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java
index 3271108995..b6bbe74b9c 100644
--- a/test/957-methodhandle-transforms/src/Main.java
+++ b/test/957-methodhandle-transforms/src/Main.java
@@ -36,6 +36,12 @@ public class Main {
testInvokers();
testSpreaders_reference();
testSpreaders_primitive();
+ testInvokeWithArguments();
+ testAsCollector();
+ testFilterArguments();
+ testCollectArguments();
+ testInsertArguments();
+ testFoldArguments();
}
public static void testThrowException() throws Throwable {
@@ -1223,6 +1229,418 @@ public class Main {
assertEquals(51, ret);
}
+ public static void testInvokeWithArguments() throws Throwable {
+ MethodType methodType = MethodType.methodType(int.class,
+ new Class<?>[] { String.class, String.class, String.class });
+ MethodHandle handle = MethodHandles.lookup().findStatic(
+ Main.class, "spreadReferences", methodType);
+
+ Object ret = handle.invokeWithArguments(new Object[] { "a", "b", "c"});
+ assertEquals(42, (int) ret);
+ handle.invokeWithArguments(new String[] { "a", "b", "c" });
+ assertEquals(42, (int) ret);
+
+ // Pass in an array that's too small. Should throw an IAE.
+ try {
+ handle.invokeWithArguments(new Object[] { "a", "b" });
+ fail();
+ } catch (IllegalArgumentException expected) {
+ } catch (WrongMethodTypeException expected) {
+ }
+
+ // Test implicit unboxing.
+ MethodType methodType2 = MethodType.methodType(int.class,
+ new Class<?>[] { String.class, int.class });
+ MethodHandle handle2 = MethodHandles.lookup().findStatic(
+ Main.class, "spreadReferences_Unbox", methodType2);
+
+ ret = (int) handle2.invokeWithArguments(new Object[] { "a", 43 });
+ assertEquals(43, (int) ret);
+ }
+
+ public static int collectBoolean(String a, boolean[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 44;
+ }
+
+ public static int collectByte(String a, byte[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 45;
+ }
+
+ public static int collectChar(String a, char[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 46;
+ }
+
+ public static int collectShort(String a, short[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 47;
+ }
+
+ public static int collectInt(String a, int[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 48;
+ }
+
+ public static int collectLong(String a, long[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 49;
+ }
+
+ public static int collectFloat(String a, float[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 50;
+ }
+
+ public static int collectDouble(String a, double[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 51;
+ }
+
+ public static int collectCharSequence(String a, CharSequence[] b) {
+ System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
+ return 99;
+ }
+
+ public static void testAsCollector() throws Throwable {
+ // Reference arrays.
+ // -------------------
+ MethodHandle trailingRef = MethodHandles.lookup().findStatic(
+ Main.class, "collectCharSequence",
+ MethodType.methodType(int.class, String.class, CharSequence[].class));
+
+ // int[] is not convertible to CharSequence[].class.
+ try {
+ trailingRef.asCollector(int[].class, 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // Object[] is not convertible to CharSequence[].class.
+ try {
+ trailingRef.asCollector(Object[].class, 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // String[].class is convertible to CharSequence.class
+ MethodHandle collector = trailingRef.asCollector(String[].class, 2);
+ assertEquals(99, (int) collector.invoke("a", "b", "c"));
+
+ // Too few arguments should fail with a WMTE.
+ try {
+ collector.invoke("a", "b");
+ fail();
+ } catch (WrongMethodTypeException expected) {
+ }
+
+ // Too many arguments should fail with a WMTE.
+ try {
+ collector.invoke("a", "b", "c", "d");
+ fail();
+ } catch (WrongMethodTypeException expected) {
+ }
+
+ // Sanity checks on other array types.
+
+ MethodHandle target = MethodHandles.lookup().findStatic(
+ Main.class, "collectBoolean",
+ MethodType.methodType(int.class, String.class, boolean[].class));
+ assertEquals(44, (int) target.asCollector(boolean[].class, 2).invoke("a", true, false));
+
+ target = MethodHandles.lookup().findStatic(Main.class, "collectByte",
+ MethodType.methodType(int.class, String.class, byte[].class));
+ assertEquals(45, (int) target.asCollector(byte[].class, 2).invoke("a", (byte) 1, (byte) 2));
+
+ target = MethodHandles.lookup().findStatic(Main.class, "collectChar",
+ MethodType.methodType(int.class, String.class, char[].class));
+ assertEquals(46, (int) target.asCollector(char[].class, 2).invoke("a", 'a', 'b'));
+
+ target = MethodHandles.lookup().findStatic(Main.class, "collectShort",
+ MethodType.methodType(int.class, String.class, short[].class));
+ assertEquals(47, (int) target.asCollector(short[].class, 2).invoke("a", (short) 3, (short) 4));
+
+ target = MethodHandles.lookup().findStatic(Main.class, "collectInt",
+ MethodType.methodType(int.class, String.class, int[].class));
+ assertEquals(48, (int) target.asCollector(int[].class, 2).invoke("a", 42, 43));
+
+ target = MethodHandles.lookup().findStatic(Main.class, "collectLong",
+ MethodType.methodType(int.class, String.class, long[].class));
+ assertEquals(49, (int) target.asCollector(long[].class, 2).invoke("a", 100, 99));
+
+ target = MethodHandles.lookup().findStatic(Main.class, "collectFloat",
+ MethodType.methodType(int.class, String.class, float[].class));
+ assertEquals(50, (int) target.asCollector(float[].class, 2).invoke("a", 8.9f, 9.1f));
+
+ target = MethodHandles.lookup().findStatic(Main.class, "collectDouble",
+ MethodType.methodType(int.class, String.class, double[].class));
+ assertEquals(51, (int) target.asCollector(double[].class, 2).invoke("a", 6.7, 7.8));
+ }
+
+ public static String filter1(char a) {
+ return String.valueOf(a);
+ }
+
+ public static char filter2(String b) {
+ return b.charAt(0);
+ }
+
+ public static String badFilter1(char a, char b) {
+ return "bad";
+ }
+
+ public static int filterTarget(String a, char b, String c, char d) {
+ System.out.println("a: " + a + ", b: " + b + ", c:" + c + ", d:" + d);
+ return 56;
+ }
+
+ public static void testFilterArguments() throws Throwable {
+ MethodHandle filter1 = MethodHandles.lookup().findStatic(
+ Main.class, "filter1", MethodType.methodType(String.class, char.class));
+ MethodHandle filter2 = MethodHandles.lookup().findStatic(
+ Main.class, "filter2", MethodType.methodType(char.class, String.class));
+
+ MethodHandle target = MethodHandles.lookup().findStatic(
+ Main.class, "filterTarget", MethodType.methodType(int.class,
+ String.class, char.class, String.class, char.class));
+
+ // In all the cases below, the values printed will be 'a', 'b', 'c', 'd'.
+
+ // Filter arguments [0, 1] - all other arguments are passed through
+ // as is.
+ MethodHandle adapter = MethodHandles.filterArguments(
+ target, 0, filter1, filter2);
+ assertEquals(56, (int) adapter.invokeExact('a', "bXXXX", "c", 'd'));
+
+ // Filter arguments [1, 2].
+ adapter = MethodHandles.filterArguments(target, 1, filter2, filter1);
+ assertEquals(56, (int) adapter.invokeExact("a", "bXXXX", 'c', 'd'));
+
+ // Filter arguments [2, 3].
+ adapter = MethodHandles.filterArguments(target, 2, filter1, filter2);
+ assertEquals(56, (int) adapter.invokeExact("a", 'b', 'c', "dXXXXX"));
+
+ // Try out a few error cases :
+
+ // The return types of the filter doesn't align with the expected argument
+ // type of the target.
+ try {
+ adapter = MethodHandles.filterArguments(target, 2, filter2, filter1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // There are more filters than arguments.
+ try {
+ adapter = MethodHandles.filterArguments(target, 3, filter2, filter1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // We pass in an obviously bogus position.
+ try {
+ adapter = MethodHandles.filterArguments(target, -1, filter2, filter1);
+ fail();
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ }
+
+ // We pass in a function that has more than one argument.
+ MethodHandle badFilter1 = MethodHandles.lookup().findStatic(
+ Main.class, "badFilter1",
+ MethodType.methodType(String.class, char.class, char.class));
+
+ try {
+ adapter = MethodHandles.filterArguments(target, 0, badFilter1, filter2);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ static void voidFilter(char a, char b) {
+ System.out.println("voidFilter");
+ }
+
+ static String filter(char a, char b) {
+ return String.valueOf(a) + "+" + b;
+ }
+
+ static char badFilter(char a, char b) {
+ return 0;
+ }
+
+ static int target(String a, String b, String c) {
+ System.out.println("a: " + a + ", b: " + b + ", c: " + c);
+ return 57;
+ }
+
+ public static void testCollectArguments() throws Throwable {
+ // Test non-void filters.
+ MethodHandle filter = MethodHandles.lookup().findStatic(
+ Main.class, "filter",
+ MethodType.methodType(String.class, char.class, char.class));
+
+ MethodHandle target = MethodHandles.lookup().findStatic(
+ Main.class, "target",
+ MethodType.methodType(int.class, String.class, String.class, String.class));
+
+ // Filter at position 0.
+ MethodHandle adapter = MethodHandles.collectArguments(target, 0, filter);
+ assertEquals(57, (int) adapter.invokeExact('a', 'b', "c", "d"));
+
+ // Filter at position 1.
+ adapter = MethodHandles.collectArguments(target, 1, filter);
+ assertEquals(57, (int) adapter.invokeExact("a", 'b', 'c', "d"));
+
+ // Filter at position 2.
+ adapter = MethodHandles.collectArguments(target, 2, filter);
+ assertEquals(57, (int) adapter.invokeExact("a", "b", 'c', 'd'));
+
+ // Test void filters. Note that we're passing in one more argument
+ // than usual because the filter returns nothing - we have to invoke with
+ // the full set of filter args and the full set of target args.
+ filter = MethodHandles.lookup().findStatic(Main.class, "voidFilter",
+ MethodType.methodType(void.class, char.class, char.class));
+ adapter = MethodHandles.collectArguments(target, 0, filter);
+ assertEquals(57, (int) adapter.invokeExact('a', 'b', "a", "b", "c"));
+
+ adapter = MethodHandles.collectArguments(target, 1, filter);
+ assertEquals(57, (int) adapter.invokeExact("a", 'a', 'b', "b", "c"));
+
+ // Test out a few failure cases.
+ filter = MethodHandles.lookup().findStatic(
+ Main.class, "filter",
+ MethodType.methodType(String.class, char.class, char.class));
+
+ // Bogus filter position.
+ try {
+ adapter = MethodHandles.collectArguments(target, 3, filter);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ // Mismatch in filter return type.
+ filter = MethodHandles.lookup().findStatic(
+ Main.class, "badFilter",
+ MethodType.methodType(char.class, char.class, char.class));
+ try {
+ adapter = MethodHandles.collectArguments(target, 0, filter);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ static int insertReceiver(String a, int b, Integer c, String d) {
+ System.out.println("a: " + a + ", b:" + b + ", c:" + c + ", d:" + d);
+ return 73;
+ }
+
+ public static void testInsertArguments() throws Throwable {
+ MethodHandle target = MethodHandles.lookup().findStatic(
+ Main.class, "insertReceiver",
+ MethodType.methodType(int.class,
+ String.class, int.class, Integer.class, String.class));
+
+ // Basic single element array inserted at position 0.
+ MethodHandle adapter = MethodHandles.insertArguments(
+ target, 0, new Object[] { "foo" });
+ assertEquals(73, (int) adapter.invokeExact(45, Integer.valueOf(56), "bar"));
+
+ // Exercise unboxing.
+ adapter = MethodHandles.insertArguments(
+ target, 1, new Object[] { Integer.valueOf(56), 57 });
+ assertEquals(73, (int) adapter.invokeExact("foo", "bar"));
+
+ // Exercise a widening conversion.
+ adapter = MethodHandles.insertArguments(
+ target, 1, new Object[] { (short) 56, Integer.valueOf(57) });
+ assertEquals(73, (int) adapter.invokeExact("foo", "bar"));
+
+ // Insert an argument at the last position.
+ adapter = MethodHandles.insertArguments(
+ target, 3, new Object[] { "bar" });
+ assertEquals(73, (int) adapter.invokeExact("foo", 45, Integer.valueOf(46)));
+
+ // Exercise a few error cases.
+
+ // A reference type that can't be cast to another reference type.
+ try {
+ MethodHandles.insertArguments(target, 3, new Object[] { new Object() });
+ fail();
+ } catch (ClassCastException expected) {
+ }
+
+ // A boxed type that can't be unboxed correctly.
+ try {
+ MethodHandles.insertArguments(target, 1, new Object[] { Long.valueOf(56) });
+ fail();
+ } catch (ClassCastException expected) {
+ }
+ }
+
+ public static String foldFilter(char a, char b) {
+ return String.valueOf(a) + "+" + b;
+ }
+
+ public static void voidFoldFilter(String e, char a, char b) {
+ System.out.println(String.valueOf(a) + "+" + b);
+ }
+
+ public static int foldTarget(String a, char b, char c, String d) {
+ System.out.println("a: " + a + " ,b:" + b + " ,c:" + c + " ,d:" + d);
+ return 89;
+ }
+
+ public static void mismatchedVoidFilter(Integer a) {
+ }
+
+ public static Integer mismatchedNonVoidFilter(char a, char b) {
+ return null;
+ }
+
+ public static void testFoldArguments() throws Throwable {
+ // Test non-void filters.
+ MethodHandle filter = MethodHandles.lookup().findStatic(
+ Main.class, "foldFilter",
+ MethodType.methodType(String.class, char.class, char.class));
+
+ MethodHandle target = MethodHandles.lookup().findStatic(
+ Main.class, "foldTarget",
+ MethodType.methodType(int.class, String.class,
+ char.class, char.class, String.class));
+
+ // Folder with a non-void type.
+ MethodHandle adapter = MethodHandles.foldArguments(target, filter);
+ assertEquals(89, (int) adapter.invokeExact('c', 'd', "e"));
+
+ // Folder with a void type.
+ filter = MethodHandles.lookup().findStatic(
+ Main.class, "voidFoldFilter",
+ MethodType.methodType(void.class, String.class, char.class, char.class));
+ adapter = MethodHandles.foldArguments(target, filter);
+ assertEquals(89, (int) adapter.invokeExact("a", 'c', 'd', "e"));
+
+ // Test a few erroneous cases.
+
+ filter = MethodHandles.lookup().findStatic(
+ Main.class, "mismatchedVoidFilter",
+ MethodType.methodType(void.class, Integer.class));
+ try {
+ adapter = MethodHandles.foldArguments(target, filter);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ filter = MethodHandles.lookup().findStatic(
+ Main.class, "mismatchedNonVoidFilter",
+ MethodType.methodType(Integer.class, char.class, char.class));
+ try {
+ adapter = MethodHandles.foldArguments(target, filter);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
public static void fail() {
System.out.println("FAIL");
Thread.dumpStack();
diff --git a/test/Android.bp b/test/Android.bp
index 89e409223e..d3244a683a 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -173,12 +173,13 @@ art_cc_library {
whole_static_libs: [
"libart-compiler-gtest",
"libart-runtime-gtest",
- "libgtest",
+ "libgtest"
],
shared_libs: [
"libartd",
"libartd-compiler",
"libbase",
+ "libbacktrace"
],
target: {
android: {
@@ -271,6 +272,8 @@ art_cc_defaults {
"929-search/search.cc",
"931-agent-thread/agent_thread.cc",
"933-misc-events/misc_events.cc",
+ "936-search-onload/search_onload.cc",
+ "944-transform-classloaders/classloader.cc",
],
shared_libs: [
"libbase",
@@ -317,6 +320,7 @@ cc_defaults {
"141-class-unload/jni_unload.cc",
"148-multithread-gc-annotations/gc_coverage.cc",
"149-suspend-all-stress/suspend_all.cc",
+ "154-gc-loop/heap_interface.cc",
"454-get-vreg/get_vreg_jni.cc",
"457-regs/regs_jni.cc",
"461-get-reference-vreg/get_reference_vreg_jni.cc",
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 5bb39fe098..742353da46 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -136,9 +136,9 @@ ifeq ($(ART_TEST_OPTIMIZING_GRAPH_COLOR),true)
COMPILER_TYPES += regalloc_gc
OPTIMIZING_COMPILER_TYPES += regalloc_gc
endif
-RELOCATE_TYPES := relocate
-ifeq ($(ART_TEST_RUN_TEST_NO_RELOCATE),true)
- RELOCATE_TYPES += no-relocate
+RELOCATE_TYPES := no-relocate
+ifeq ($(ART_TEST_RUN_TEST_RELOCATE),true)
+ RELOCATE_TYPES += relocate
endif
ifeq ($(ART_TEST_RUN_TEST_RELOCATE_NO_PATCHOAT),true)
RELOCATE_TYPES += relocate-npatchoat
@@ -161,7 +161,9 @@ JNI_TYPES := checkjni
ifeq ($(ART_TEST_JNI_FORCECOPY),true)
JNI_TYPES += forcecopy
endif
+ifeq ($(ART_TEST_RUN_TEST_IMAGE),true)
IMAGE_TYPES := picimage
+endif
ifeq ($(ART_TEST_RUN_TEST_NO_IMAGE),true)
IMAGE_TYPES += no-image
endif
@@ -379,6 +381,7 @@ TEST_ART_BROKEN_INTERPRETER_ACCESS_CHECK_TESTS :=
# slows down allocations significantly which these tests do a lot.
TEST_ART_BROKEN_GCSTRESS_RUN_TESTS := \
137-cfi \
+ 154-gc-loop \
908-gc-start-finish \
913-heaps \
961-default-iface-resolution-gen \
@@ -436,13 +439,14 @@ TEST_ART_BROKEN_FALLBACK_RUN_TESTS := \
629-vdex-speed
# This test fails without an image.
-# 018, 961, 964 often time out. b/34369284
+# 018, 961, 964, 968 often time out. b/34369284
TEST_ART_BROKEN_NO_IMAGE_RUN_TESTS := \
137-cfi \
138-duplicate-classes-check \
018-stack-overflow \
961-default-iface-resolution-gen \
- 964-default-iface-init
+ 964-default-iface-init \
+ 968-default-partial-compile-gen \
ifneq (,$(filter no-dex2oat,$(PREBUILD_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),no-dex2oat, \
@@ -604,6 +608,7 @@ TEST_ART_BROKEN_OPTIMIZING_MIPS64_RUN_TESTS :=
TEST_ART_BROKEN_OPTIMIZING_NONDEBUGGABLE_RUN_TESTS := \
454-get-vreg \
457-regs \
+ 602-deoptimizeable
ifneq (,$(filter $(OPTIMIZING_COMPILER_TYPES),$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
@@ -706,8 +711,10 @@ endif
TEST_ART_BROKEN_OPTIMIZING_HEAP_POISONING_RUN_TESTS :=
-# Tests that check semantics for a non-debuggable app.
+# 909: Tests that check semantics for a non-debuggable app.
+# 137: relies on AOT code and debuggable makes us JIT always.
TEST_ART_BROKEN_DEBUGGABLE_RUN_TESTS := \
+ 137-cfi \
909-attach-agent \
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
diff --git a/test/ErroneousInit/ErroneousInit.java b/test/ErroneousInit/ErroneousInit.java
new file mode 100644
index 0000000000..67b7b204dc
--- /dev/null
+++ b/test/ErroneousInit/ErroneousInit.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+class ErroneousInit {
+ static {
+ if (true) {
+ throw new Error();
+ }
+ }
+}
diff --git a/test/Nested/Nested.java b/test/Nested/Nested.java
index 78b273bec0..f493989268 100644
--- a/test/Nested/Nested.java
+++ b/test/Nested/Nested.java
@@ -17,4 +17,6 @@
class Nested {
class Inner {
}
+ Object x = new Object() {
+ };
}
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 28fa130443..186a1513ee 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -39,7 +39,7 @@ OPTIMIZE="y"
PATCHOAT=""
PREBUILD="y"
QUIET="n"
-RELOCATE="y"
+RELOCATE="n"
STRIP_DEX="n"
SECONDARY_DEX=""
TIME_OUT="gdb" # "n" (disabled), "timeout" (use timeout), "gdb" (use gdb)
@@ -344,7 +344,7 @@ if [ "$IS_JVMTI_TEST" = "y" ]; then
else
FLAGS="${FLAGS} -agentpath:${agent}=${TEST_NAME},art"
FLAGS="${FLAGS} -Xplugin:${plugin}"
- FLAGS="${FLAGS} -Xfully-deoptable"
+ FLAGS="${FLAGS} -Xcompiler-option --debuggable"
# Always make the compilation be debuggable.
COMPILE_FLAGS="${COMPILE_FLAGS} --debuggable"
fi
@@ -364,6 +364,8 @@ fi
if [ "$HAVE_IMAGE" = "n" ]; then
+ # Add 5 minutes to give some time to generate the boot image.
+ TIME_OUT_VALUE=$((${TIME_OUT_VALUE} + 300))
DALVIKVM_BOOT_OPT="-Ximage:/system/non-existant/core.art"
else
DALVIKVM_BOOT_OPT="-Ximage:${BOOT_IMAGE}"
diff --git a/test/run-test b/test/run-test
index c78fa35e24..27c700e89e 100755
--- a/test/run-test
+++ b/test/run-test
@@ -111,7 +111,7 @@ target_mode="yes"
dev_mode="no"
update_mode="no"
debug_mode="no"
-relocate="yes"
+relocate="no"
runtime="art"
usage="no"
build_only="no"
@@ -156,6 +156,7 @@ while true; do
shift
elif [ "x$1" = "x--jvm" ]; then
target_mode="no"
+ DEX_LOCATION="$tmp_dir"
runtime="jvm"
image_args=""
prebuild_mode="no"
@@ -408,7 +409,9 @@ tmp_dir="`cd $oldwd ; python -c "import os; print os.path.realpath('$tmp_dir')"`
mkdir -p $tmp_dir
# Add thread suspend timeout flag
-run_args="${run_args} --runtime-option -XX:ThreadSuspendTimeout=$suspend_timeout"
+if [ ! "$runtime" = "jvm" ]; then
+ run_args="${run_args} --runtime-option -XX:ThreadSuspendTimeout=$suspend_timeout"
+fi
if [ "$basic_verify" = "true" ]; then
# Set HspaceCompactForOOMMinIntervalMs to zero to run hspace compaction for OOM more frequently in tests.
@@ -624,8 +627,8 @@ if [ "$usage" = "yes" ]; then
echo " --strip-dex Strip the dex files before starting test."
echo " --relocate Force the use of relocating in the test, making"
echo " the image and oat files be relocated to a random"
- echo " address before running. (default)"
- echo " --no-relocate Force the use of no relocating in the test"
+ echo " address before running."
+ echo " --no-relocate Force the use of no relocating in the test. (default)"
echo " --image Run the test using a precompiled boot image. (default)"
echo " --no-image Run the test without a precompiled boot image."
echo " --host Use the host-mode virtual machine."
diff --git a/test/ti-agent/common_helper.cc b/test/ti-agent/common_helper.cc
index 80e1797369..ea6359e5e0 100644
--- a/test/ti-agent/common_helper.cc
+++ b/test/ti-agent/common_helper.cc
@@ -210,6 +210,7 @@ struct CommonTransformationResult {
// Map from class name to transformation result.
std::map<std::string, std::deque<CommonTransformationResult>> gTransformations;
+bool gPopTransformations = true;
extern "C" JNIEXPORT void JNICALL Java_Main_addCommonTransformationResult(JNIEnv* env,
jclass,
@@ -266,7 +267,32 @@ void JNICALL CommonClassFileLoadHookRetransformable(jvmtiEnv* jvmti_env,
memcpy(new_data, desired_array.data(), desired_array.size());
*new_class_data = new_data;
*new_class_data_len = desired_array.size();
+ if (gPopTransformations) {
+ gTransformations[name_str].pop_front();
+ }
+ }
+}
+
+extern "C" JNIEXPORT void Java_Main_setPopRetransformations(JNIEnv*,
+ jclass,
+ jboolean enable) {
+ gPopTransformations = enable;
+}
+
+extern "C" JNIEXPORT void Java_Main_popTransformationFor(JNIEnv* env,
+ jclass,
+ jstring class_name) {
+ const char* name_chrs = env->GetStringUTFChars(class_name, nullptr);
+ std::string name_str(name_chrs);
+ env->ReleaseStringUTFChars(class_name, name_chrs);
+ if (gTransformations.find(name_str) != gTransformations.end() &&
+ gTransformations[name_str].size() > 0) {
gTransformations[name_str].pop_front();
+ } else {
+ std::stringstream err;
+ err << "No transformations found for class " << name_str;
+ std::string message = err.str();
+ env->ThrowNew(env->FindClass("java/lang/Exception"), message.c_str());
}
}
@@ -301,11 +327,36 @@ static void DoClassRetransformation(jvmtiEnv* jvmti_env, JNIEnv* env, jobjectArr
}
}
-// TODO Write something useful.
extern "C" JNIEXPORT void JNICALL Java_Main_doCommonClassRetransformation(JNIEnv* env,
jclass,
jobjectArray targets) {
- DoClassRetransformation(jvmti_env, env, targets);
+ jvmtiCapabilities caps;
+ jvmtiError caps_err = jvmti_env->GetCapabilities(&caps);
+ if (caps_err != JVMTI_ERROR_NONE) {
+ env->ThrowNew(env->FindClass("java/lang/Exception"),
+ "Unable to get current jvmtiEnv capabilities");
+ return;
+ }
+
+ // Allocate a new environment if we don't have the can_retransform_classes capability needed to
+ // call the RetransformClasses function.
+ jvmtiEnv* real_env = nullptr;
+ if (caps.can_retransform_classes != 1) {
+ JavaVM* vm = nullptr;
+ if (env->GetJavaVM(&vm) != 0 ||
+ vm->GetEnv(reinterpret_cast<void**>(&real_env), JVMTI_VERSION_1_0) != 0) {
+ env->ThrowNew(env->FindClass("java/lang/Exception"),
+ "Unable to create temporary jvmtiEnv for RetransformClasses call.");
+ return;
+ }
+ SetAllCapabilities(real_env);
+ } else {
+ real_env = jvmti_env;
+ }
+ DoClassRetransformation(real_env, env, targets);
+ if (caps.can_retransform_classes != 1) {
+ real_env->DisposeEnvironment();
+ }
}
// Get all capabilities except those related to retransformation.
@@ -329,6 +380,38 @@ jint OnLoad(JavaVM* vm,
} // namespace common_retransform
+namespace common_transform {
+
+using art::common_retransform::CommonClassFileLoadHookRetransformable;
+
+// Get all capabilities except those related to retransformation.
+jint OnLoad(JavaVM* vm,
+ char* options ATTRIBUTE_UNUSED,
+ void* reserved ATTRIBUTE_UNUSED) {
+ if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
+ printf("Unable to get jvmti env!\n");
+ return 1;
+ }
+ // Don't set the retransform caps
+ jvmtiCapabilities caps;
+ jvmti_env->GetPotentialCapabilities(&caps);
+ caps.can_retransform_classes = 0;
+ caps.can_retransform_any_class = 0;
+ jvmti_env->AddCapabilities(&caps);
+
+ // Use the same callback as the retransform test.
+ jvmtiEventCallbacks cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.ClassFileLoadHook = CommonClassFileLoadHookRetransformable;
+ if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
+ printf("Unable to set class file load hook cb!\n");
+ return 1;
+ }
+ return 0;
+}
+
+} // namespace common_transform
+
static void BindMethod(jvmtiEnv* jenv,
JNIEnv* env,
jclass klass,
@@ -340,15 +423,29 @@ static void BindMethod(jvmtiEnv* jenv,
LOG(FATAL) << "Could not get methods";
}
- ArtMethod* m = jni::DecodeArtMethod(method);
-
std::string names[2];
- {
+ if (IsJVM()) {
+ // TODO Get the JNI long name
+ char* klass_name;
+ jvmtiError klass_result = jenv->GetClassSignature(klass, &klass_name, nullptr);
+ if (klass_result == JVMTI_ERROR_NONE) {
+ std::string name_str(name);
+ std::string klass_str(klass_name);
+ names[0] = GetJniShortName(klass_str, name_str);
+ jenv->Deallocate(reinterpret_cast<unsigned char*>(klass_name));
+ } else {
+ LOG(FATAL) << "Could not get class name!";
+ }
+ } else {
ScopedObjectAccess soa(Thread::Current());
+ ArtMethod* m = jni::DecodeArtMethod(method);
names[0] = m->JniShortName();
names[1] = m->JniLongName();
}
for (const std::string& mangled_name : names) {
+ if (mangled_name == "") {
+ continue;
+ }
void* sym = dlsym(RTLD_DEFAULT, mangled_name.c_str());
if (sym == nullptr) {
continue;
diff --git a/test/ti-agent/common_helper.h b/test/ti-agent/common_helper.h
index c60553dc5a..031850147e 100644
--- a/test/ti-agent/common_helper.h
+++ b/test/ti-agent/common_helper.h
@@ -27,10 +27,15 @@ namespace common_redefine {
jint OnLoad(JavaVM* vm, char* options, void* reserved);
} // namespace common_redefine
+
namespace common_retransform {
jint OnLoad(JavaVM* vm, char* options, void* reserved);
} // namespace common_retransform
+namespace common_transform {
+jint OnLoad(JavaVM* vm, char* options, void* reserved);
+} // namespace common_transform
+
extern bool RuntimeIsJVM;
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 8ed8e67e42..c5a93568c6 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -28,6 +28,7 @@
#include "901-hello-ti-agent/basics.h"
#include "909-attach-agent/attach.h"
+#include "936-search-onload/search_onload.h"
namespace art {
@@ -110,6 +111,17 @@ static AgentLib agents[] = {
{ "926-multi-obsolescence", common_redefine::OnLoad, nullptr },
{ "930-hello-retransform", common_retransform::OnLoad, nullptr },
{ "932-transform-saves", common_retransform::OnLoad, nullptr },
+ { "934-load-transform", common_retransform::OnLoad, nullptr },
+ { "935-non-retransformable", common_transform::OnLoad, nullptr },
+ { "936-search-onload", Test936SearchOnload::OnLoad, nullptr },
+ { "937-hello-retransform-package", common_retransform::OnLoad, nullptr },
+ { "938-load-transform-bcp", common_retransform::OnLoad, nullptr },
+ { "939-hello-transformation-bcp", common_redefine::OnLoad, nullptr },
+ { "940-recursive-obsolete", common_redefine::OnLoad, nullptr },
+ { "941-recursive-obsolete-jit", common_redefine::OnLoad, nullptr },
+ { "942-private-recursive", common_redefine::OnLoad, nullptr },
+ { "943-private-recursive-jit", common_redefine::OnLoad, nullptr },
+ { "944-transform-classloaders", common_redefine::OnLoad, nullptr },
};
static AgentLib* FindAgent(char* name) {