summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/529-checker-unresolved/src/Main.java4
-rw-r--r--test/536-checker-intrinsic-optimization/src/Main.java8
-rw-r--r--test/621-checker-new-instance/info.txt1
-rw-r--r--test/621-checker-new-instance/src/Main.java53
-rw-r--r--test/631-checker-get-class/expected.txt (renamed from test/621-checker-new-instance/expected.txt)0
-rw-r--r--test/631-checker-get-class/info.txt4
-rw-r--r--test/631-checker-get-class/src/Main.java99
-rw-r--r--test/632-checker-char-at-bounds/expected.txt0
-rw-r--r--test/632-checker-char-at-bounds/info.txt2
-rw-r--r--test/632-checker-char-at-bounds/src/Main.java40
-rw-r--r--test/903-hello-tagging/tagging.cc3
-rw-r--r--test/904-object-allocation/tracking.cc2
-rw-r--r--test/905-object-free/tracking_free.cc2
-rw-r--r--test/906-iterate-heap/iterate_heap.cc1
-rw-r--r--test/907-get-loaded-classes/get_loaded_classes.cc1
-rw-r--r--test/908-gc-start-finish/gc_callbacks.cc3
-rw-r--r--test/910-methods/expected.txt44
-rw-r--r--test/910-methods/methods.cc97
-rw-r--r--test/910-methods/src/Main.java73
-rw-r--r--test/911-get-stack-trace/stack_trace.cc3
-rw-r--r--test/912-classes/classes.cc163
-rw-r--r--test/912-classes/expected.txt38
-rw-r--r--test/912-classes/src/Main.java130
-rw-r--r--test/913-heaps/heaps.cc2
-rwxr-xr-xtest/918-fields/build17
-rw-r--r--test/918-fields/expected.txt16
-rw-r--r--test/918-fields/fields.cc148
-rw-r--r--test/918-fields/fields.h30
-rw-r--r--test/918-fields/info.txt1
-rwxr-xr-xtest/918-fields/run19
-rw-r--r--test/918-fields/src/Main.java70
-rwxr-xr-xtest/919-obsolete-fields/build17
-rw-r--r--test/919-obsolete-fields/expected.txt21
-rw-r--r--test/919-obsolete-fields/info.txt1
-rwxr-xr-xtest/919-obsolete-fields/run19
-rw-r--r--test/919-obsolete-fields/src/Main.java155
-rw-r--r--test/919-obsolete-fields/src/Transform.java47
-rwxr-xr-xtest/920-objects/build17
-rw-r--r--test/920-objects/expected.txt10
-rw-r--r--test/920-objects/info.txt1
-rw-r--r--test/920-objects/objects.cc77
-rw-r--r--test/920-objects/objects.h30
-rwxr-xr-xtest/920-objects/run19
-rw-r--r--test/920-objects/src/Main.java98
-rwxr-xr-xtest/921-hello-failure/build17
-rw-r--r--test/921-hello-failure/expected.txt15
-rw-r--r--test/921-hello-failure/info.txt7
-rwxr-xr-xtest/921-hello-failure/run20
-rw-r--r--test/921-hello-failure/src/DifferentAccess.java57
-rw-r--r--test/921-hello-failure/src/Iface1.java19
-rw-r--r--test/921-hello-failure/src/Iface2.java19
-rw-r--r--test/921-hello-failure/src/Iface3.java19
-rw-r--r--test/921-hello-failure/src/Main.java32
-rw-r--r--test/921-hello-failure/src/MissingInterface.java58
-rw-r--r--test/921-hello-failure/src/NewInterface.java59
-rw-r--r--test/921-hello-failure/src/NewName.java56
-rw-r--r--test/921-hello-failure/src/ReorderInterface.java59
-rw-r--r--test/921-hello-failure/src/Transform.java21
-rw-r--r--test/921-hello-failure/src/Transform2.java21
-rwxr-xr-xtest/922-properties/build17
-rw-r--r--test/922-properties/expected.txt59
-rw-r--r--test/922-properties/info.txt1
-rw-r--r--test/922-properties/properties.cc107
-rw-r--r--test/922-properties/properties.h30
-rwxr-xr-xtest/922-properties/run19
-rw-r--r--test/922-properties/src/Main.java155
-rw-r--r--test/Android.bp3
-rw-r--r--test/Android.run-test.mk14
-rw-r--r--test/ti-agent/common_helper.cc41
-rw-r--r--test/ti-agent/common_helper.h2
-rw-r--r--test/ti-agent/common_load.cc8
-rw-r--r--test/valgrind-target-suppressions.txt12
72 files changed, 2464 insertions, 69 deletions
diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java
index 5fd51e1dca..89b9cb45c3 100644
--- a/test/529-checker-unresolved/src/Main.java
+++ b/test/529-checker-unresolved/src/Main.java
@@ -192,13 +192,13 @@ public class Main extends UnresolvedSuperClass {
/// CHECK-START: void Main.testLicm(int) licm (before)
/// CHECK: <<Class:l\d+>> LoadClass loop:B2
/// CHECK-NEXT: <<Clinit:l\d+>> ClinitCheck [<<Class>>] loop:B2
- /// CHECK-NEXT: <<New:l\d+>> NewInstance [<<Clinit>>,<<Method:[i|j]\d+>>] loop:B2
+ /// CHECK-NEXT: <<New:l\d+>> NewInstance [<<Clinit>>] loop:B2
/// CHECK-NEXT: InvokeUnresolved [<<New>>] loop:B2
/// CHECK-START: void Main.testLicm(int) licm (after)
/// CHECK: <<Class:l\d+>> LoadClass loop:none
/// CHECK-NEXT: <<Clinit:l\d+>> ClinitCheck [<<Class>>] loop:none
- /// CHECK: <<New:l\d+>> NewInstance [<<Clinit>>,<<Method:[i|j]\d+>>] loop:B2
+ /// CHECK: <<New:l\d+>> NewInstance [<<Clinit>>] loop:B2
/// CHECK-NEXT: InvokeUnresolved [<<New>>] loop:B2
static public void testLicm(int count) {
// Test to make sure we keep the initialization check after loading an unresolved class.
diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java
index 26475ae55c..ed7524c7ad 100644
--- a/test/536-checker-intrinsic-optimization/src/Main.java
+++ b/test/536-checker-intrinsic-optimization/src/Main.java
@@ -153,8 +153,8 @@ public class Main {
/// CHECK-DAG: <<Pos:i\d+>> ParameterValue
/// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>]
/// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true
- /// CHECK-DAG: BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
- /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Pos>>] is_string_char_at:true
+ /// CHECK-DAG: <<Bounds:i\d+>> BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
+ /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
/// CHECK-DAG: Return [<<Char>>]
/// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (after)
@@ -174,8 +174,8 @@ public class Main {
/// CHECK-DAG: <<Pos:i\d+>> ParameterValue
/// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>]
/// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true
- /// CHECK-DAG: BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
- /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Pos>>] is_string_char_at:true
+ /// CHECK-DAG: <<Bounds:i\d+>> BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
+ /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
/// CHECK-DAG: Return [<<Char>>]
/// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after)
diff --git a/test/621-checker-new-instance/info.txt b/test/621-checker-new-instance/info.txt
deleted file mode 100644
index c27c45ca7f..0000000000
--- a/test/621-checker-new-instance/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Tests for removing useless load class.
diff --git a/test/621-checker-new-instance/src/Main.java b/test/621-checker-new-instance/src/Main.java
deleted file mode 100644
index 68a46449f0..0000000000
--- a/test/621-checker-new-instance/src/Main.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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 {
- /// CHECK-START: java.lang.Object Main.newObject() prepare_for_register_allocation (before)
- /// CHECK: LoadClass
- /// CHECK: NewInstance
-
- /// CHECK-START: java.lang.Object Main.newObject() prepare_for_register_allocation (after)
- /// CHECK-NOT: LoadClass
- /// CHECK: NewInstance
- public static Object newObject() {
- return new Object();
- }
-
- /// CHECK-START: java.lang.Object Main.newFinalizableMayThrow() prepare_for_register_allocation (after)
- /// CHECK: LoadClass
- /// CHECK: NewInstance
- public static Object newFinalizableMayThrow() {
- return $inline$newFinalizableMayThrow();
- }
-
- public static Object $inline$newFinalizableMayThrow() {
- return new FinalizableMayThrow();
- }
-
- public static void main(String[] args) {
- newFinalizableMayThrow();
- newObject();
- }
-}
-
-class FinalizableMayThrow {
- // clinit may throw OOME.
- static Object o = new Object();
- static String s;
- public void finalize() {
- s = "Test";
- }
-}
diff --git a/test/621-checker-new-instance/expected.txt b/test/631-checker-get-class/expected.txt
index e69de29bb2..e69de29bb2 100644
--- a/test/621-checker-new-instance/expected.txt
+++ b/test/631-checker-get-class/expected.txt
diff --git a/test/631-checker-get-class/info.txt b/test/631-checker-get-class/info.txt
new file mode 100644
index 0000000000..f236a22e1f
--- /dev/null
+++ b/test/631-checker-get-class/info.txt
@@ -0,0 +1,4 @@
+Checker test to make sure we recognize the pattern:
+if (foo.getClass() == Foo.class)
+
+For doing better type propagation.
diff --git a/test/631-checker-get-class/src/Main.java b/test/631-checker-get-class/src/Main.java
new file mode 100644
index 0000000000..61c0adf624
--- /dev/null
+++ b/test/631-checker-get-class/src/Main.java
@@ -0,0 +1,99 @@
+/*
+ * 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 {
+
+ /// CHECK-START: int Main.bar(Main) inliner (before)
+ /// CHECK: InvokeVirtual
+ /// CHECK: InvokeVirtual
+
+ /// CHECK-START: int Main.bar(Main) inliner (after)
+ /// CHECK-NOT: InvokeVirtual
+ public static int bar(Main m) {
+ if (m.getClass() == Main.class) {
+ return m.foo();
+ }
+ return 4;
+ }
+
+ public int foo() {
+ return 42;
+ }
+
+ /// CHECK-START: boolean Main.classEquality1() instruction_simplifier$after_inlining (before)
+ /// CHECK-DAG: <<Eq:z\d+>> {{Equal|NotEqual}}
+ /// CHECK-DAG: <<Select:i\d+>> Select [{{i\d+}},{{i\d+}},<<Eq>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: boolean Main.classEquality1() instruction_simplifier$after_inlining (after)
+ /// CHECK-DAG: <<Constant:i\d+>> IntConstant 1
+ /// CHECK-DAG: Return [<<Constant>>]
+ public static boolean classEquality1() {
+ return new Main().getClass() == Main.class;
+ }
+
+ /// CHECK-START: boolean Main.classEquality2() instruction_simplifier$after_inlining (before)
+ /// CHECK-DAG: <<Eq:z\d+>> {{Equal|NotEqual}}
+ /// CHECK-DAG: <<Select:i\d+>> Select [{{i\d+}},{{i\d+}},<<Eq>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: boolean Main.classEquality2() instruction_simplifier$after_inlining (after)
+ /// CHECK-DAG: <<Constant:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Constant>>]
+ public static boolean classEquality2() {
+ Object o = new SubMain();
+ return o.getClass() == Main.class;
+ }
+
+ /// CHECK-START: boolean Main.classEquality3() instruction_simplifier$after_inlining (before)
+ /// CHECK-DAG: <<Eq:z\d+>> {{Equal|NotEqual}}
+ /// CHECK-DAG: <<Select:i\d+>> Select [{{i\d+}},{{i\d+}},<<Eq>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: boolean Main.classEquality3() instruction_simplifier$after_inlining (after)
+ /// CHECK-DAG: <<Constant:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Constant>>]
+ public static boolean classEquality3() {
+ return new Main().getClass() != Main.class;
+ }
+
+ /// CHECK-START: boolean Main.classEquality4() instruction_simplifier$after_inlining (before)
+ /// CHECK-DAG: <<Eq:z\d+>> {{Equal|NotEqual}}
+ /// CHECK-DAG: <<Select:i\d+>> Select [{{i\d+}},{{i\d+}},<<Eq>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: boolean Main.classEquality4() instruction_simplifier$after_inlining (after)
+ /// CHECK-DAG: <<Constant:i\d+>> IntConstant 1
+ /// CHECK-DAG: Return [<<Constant>>]
+ public static boolean classEquality4() {
+ Object o = new SubMain();
+ return o.getClass() != Main.class;
+ }
+
+ public static void main(String[] args) {
+ int actual = bar(new Main());
+ if (actual != 42) {
+ throw new Error("Expected 42, got " + actual);
+ }
+ actual = bar(new SubMain());
+ if (actual != 4) {
+ throw new Error("Expected 4, got " + actual);
+ }
+ }
+}
+
+class SubMain extends Main {
+}
diff --git a/test/632-checker-char-at-bounds/expected.txt b/test/632-checker-char-at-bounds/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/632-checker-char-at-bounds/expected.txt
diff --git a/test/632-checker-char-at-bounds/info.txt b/test/632-checker-char-at-bounds/info.txt
new file mode 100644
index 0000000000..10b9a447d4
--- /dev/null
+++ b/test/632-checker-char-at-bounds/info.txt
@@ -0,0 +1,2 @@
+Regression test for the optimization of String.charAt, which
+had its SSA dependency incorrect with its corresponding bound check.
diff --git a/test/632-checker-char-at-bounds/src/Main.java b/test/632-checker-char-at-bounds/src/Main.java
new file mode 100644
index 0000000000..65022d0af9
--- /dev/null
+++ b/test/632-checker-char-at-bounds/src/Main.java
@@ -0,0 +1,40 @@
+/*
+ * 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 {
+
+ /// CHECK-START: void Main.main(java.lang.String[]) licm (after)
+ /// CHECK-DAG: <<NullCheck:l\d+>> NullCheck
+ /// CHECK-DAG: <<BoundsCheck:i\d+>> BoundsCheck
+ /// CHECK-DAG: ArrayGet [<<NullCheck>>,<<BoundsCheck>>]
+ public static void main(String[] args) {
+ try {
+ String foo = myString;
+ foo.getClass(); // Make sure the null check is not in the loop.
+ char c = 0;
+ for (int i = 0; i < 10; i++) {
+ // The charAt may be licm'ed, but it has to be licm'ed with its
+ // bounds check.
+ c = foo.charAt(10000000);
+ }
+ System.out.println(c);
+ } catch (StringIndexOutOfBoundsException e) {
+ // Expected
+ }
+ }
+
+ static String myString = "foo";
+}
diff --git a/test/903-hello-tagging/tagging.cc b/test/903-hello-tagging/tagging.cc
index 1557d45a6a..60a31bdd2d 100644
--- a/test/903-hello-tagging/tagging.cc
+++ b/test/903-hello-tagging/tagging.cc
@@ -44,6 +44,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setTag(JNIEnv* env ATTRIBUTE_UNUSED,
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error setting tag: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
@@ -56,6 +57,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_getTag(JNIEnv* env ATTRIBUTE_UNUSED
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error getting tag: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
return tag;
}
@@ -90,6 +92,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getTaggedObjects(JNIEnv* env
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Failure running GetLoadedClasses: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
diff --git a/test/904-object-allocation/tracking.cc b/test/904-object-allocation/tracking.cc
index 9261a9f9a1..f993606b42 100644
--- a/test/904-object-allocation/tracking.cc
+++ b/test/904-object-allocation/tracking.cc
@@ -69,6 +69,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setupObjectAllocCallback(
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error setting callbacks: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
@@ -84,6 +85,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableAllocationTracking(JNIEnv* env
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error enabling/disabling allocation tracking: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
diff --git a/test/905-object-free/tracking_free.cc b/test/905-object-free/tracking_free.cc
index fc43acce79..7f295accb2 100644
--- a/test/905-object-free/tracking_free.cc
+++ b/test/905-object-free/tracking_free.cc
@@ -50,6 +50,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setupObjectFreeCallback(
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error setting callbacks: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
@@ -64,6 +65,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableFreeTracking(JNIEnv* env ATTRI
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error enabling/disabling object-free callbacks: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
diff --git a/test/906-iterate-heap/iterate_heap.cc b/test/906-iterate-heap/iterate_heap.cc
index 8dac89d1a5..a2fd59128f 100644
--- a/test/906-iterate-heap/iterate_heap.cc
+++ b/test/906-iterate-heap/iterate_heap.cc
@@ -61,6 +61,7 @@ static bool Run(jint heap_filter, jclass klass_filter, IterationConfig* config)
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Failure running IterateThroughHeap: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return false;
}
return true;
diff --git a/test/907-get-loaded-classes/get_loaded_classes.cc b/test/907-get-loaded-classes/get_loaded_classes.cc
index afbb77415e..36d33b63cc 100644
--- a/test/907-get-loaded-classes/get_loaded_classes.cc
+++ b/test/907-get-loaded-classes/get_loaded_classes.cc
@@ -48,6 +48,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getLoadedClasses(
char* err;
jvmti_env->GetErrorName(result, &err);
printf("Failure running GetLoadedClasses: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
diff --git a/test/908-gc-start-finish/gc_callbacks.cc b/test/908-gc-start-finish/gc_callbacks.cc
index 771d1adae6..1fab79dcb1 100644
--- a/test/908-gc-start-finish/gc_callbacks.cc
+++ b/test/908-gc-start-finish/gc_callbacks.cc
@@ -51,6 +51,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setupGcCallback(
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error setting callbacks: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
@@ -65,6 +66,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableGcTracking(JNIEnv* env ATTRIBU
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error enabling/disabling gc callbacks: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
ret = jvmti_env->SetEventNotificationMode(
enable ? JVMTI_ENABLE : JVMTI_DISABLE,
@@ -74,6 +76,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableGcTracking(JNIEnv* env ATTRIBU
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error enabling/disabling gc callbacks: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
diff --git a/test/910-methods/expected.txt b/test/910-methods/expected.txt
index 9a747994fe..c913b3ffe5 100644
--- a/test/910-methods/expected.txt
+++ b/test/910-methods/expected.txt
@@ -1,15 +1,59 @@
[toString, ()Ljava/lang/String;, null]
class java.lang.Object
1
+Max locals: 3
+Argument size: 1
+Location start: 0
+Location end: 40
+Is native: false
+Is obsolete: false
+Is synthetic: false
[charAt, (I)C, null]
class java.lang.String
257
+Max locals: JVMTI_ERROR_NATIVE_METHOD
+Argument size: JVMTI_ERROR_NATIVE_METHOD
+Location start: JVMTI_ERROR_NATIVE_METHOD
+Location end: JVMTI_ERROR_NATIVE_METHOD
+Is native: true
+Is obsolete: false
+Is synthetic: false
[sqrt, (D)D, null]
class java.lang.Math
265
+Max locals: JVMTI_ERROR_NATIVE_METHOD
+Argument size: JVMTI_ERROR_NATIVE_METHOD
+Location start: JVMTI_ERROR_NATIVE_METHOD
+Location end: JVMTI_ERROR_NATIVE_METHOD
+Is native: true
+Is obsolete: false
+Is synthetic: false
[add, (Ljava/lang/Object;)Z, null]
interface java.util.List
1025
+Max locals: 0
+Argument size: 0
+Location start: 0
+Location end: 0
+Is native: false
+Is obsolete: false
+Is synthetic: false
[run, ()V, null]
class $Proxy0
17
+Max locals: 0
+Argument size: 0
+Location start: 0
+Location end: 0
+Is native: false
+Is obsolete: false
+Is synthetic: false
+class Main$NestedSynthetic
+4104
+Max locals: 1
+Argument size: 0
+Location start: 0
+Location end: 2
+Is native: false
+Is obsolete: false
+Is synthetic: true
diff --git a/test/910-methods/methods.cc b/test/910-methods/methods.cc
index 3ed91d7a17..fa9679db4b 100644
--- a/test/910-methods/methods.cc
+++ b/test/910-methods/methods.cc
@@ -41,6 +41,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getMethodName(
char* err;
jvmti_env->GetErrorName(result, &err);
printf("Failure running GetMethodName: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
@@ -72,6 +73,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getMethodName(
char* err;
jvmti_env->GetErrorName(result2, &err);
printf("Failure running GetMethodName(null, null, null): %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
@@ -88,6 +90,7 @@ extern "C" JNIEXPORT jclass JNICALL Java_Main_getMethodDeclaringClass(
char* err;
jvmti_env->GetErrorName(result, &err);
printf("Failure running GetMethodDeclaringClass: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
@@ -104,12 +107,106 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_getMethodModifiers(
char* err;
jvmti_env->GetErrorName(result, &err);
printf("Failure running GetMethodModifiers: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return 0;
}
return modifiers;
}
+extern "C" JNIEXPORT jint JNICALL Java_Main_getMaxLocals(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+ jmethodID id = env->FromReflectedMethod(method);
+
+ jint max_locals;
+ jvmtiError result = jvmti_env->GetMaxLocals(id, &max_locals);
+ if (JvmtiErrorToException(env, result)) {
+ return -1;
+ }
+
+ return max_locals;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getArgumentsSize(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+ jmethodID id = env->FromReflectedMethod(method);
+
+ jint arguments;
+ jvmtiError result = jvmti_env->GetArgumentsSize(id, &arguments);
+ if (JvmtiErrorToException(env, result)) {
+ return -1;
+ }
+
+ return arguments;
+}
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_getMethodLocationStart(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+ jmethodID id = env->FromReflectedMethod(method);
+
+ jlong start;
+ jlong end;
+ jvmtiError result = jvmti_env->GetMethodLocation(id, &start, &end);
+ if (JvmtiErrorToException(env, result)) {
+ return -1;
+ }
+
+ return start;
+}
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_getMethodLocationEnd(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+ jmethodID id = env->FromReflectedMethod(method);
+
+ jlong start;
+ jlong end;
+ jvmtiError result = jvmti_env->GetMethodLocation(id, &start, &end);
+ if (JvmtiErrorToException(env, result)) {
+ return -1;
+ }
+
+ return end;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isMethodNative(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+ jmethodID id = env->FromReflectedMethod(method);
+
+ jboolean is_native;
+ jvmtiError result = jvmti_env->IsMethodNative(id, &is_native);
+ if (JvmtiErrorToException(env, result)) {
+ return JNI_FALSE;
+ }
+
+ return is_native;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isMethodObsolete(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+ jmethodID id = env->FromReflectedMethod(method);
+
+ jboolean is_obsolete;
+ jvmtiError result = jvmti_env->IsMethodObsolete(id, &is_obsolete);
+ if (JvmtiErrorToException(env, result)) {
+ return JNI_FALSE;
+ }
+
+ return is_obsolete;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isMethodSynthetic(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+ jmethodID id = env->FromReflectedMethod(method);
+
+ jboolean is_synthetic;
+ jvmtiError result = jvmti_env->IsMethodSynthetic(id, &is_synthetic);
+ if (JvmtiErrorToException(env, result)) {
+ return JNI_FALSE;
+ }
+
+ return is_synthetic;
+}
+
// Don't do anything
jint OnLoad(JavaVM* vm,
char* options ATTRIBUTE_UNUSED,
diff --git a/test/910-methods/src/Main.java b/test/910-methods/src/Main.java
index 3459134ea2..bf25a0d028 100644
--- a/test/910-methods/src/Main.java
+++ b/test/910-methods/src/Main.java
@@ -32,6 +32,10 @@ public class Main {
testMethod("java.util.List", "add", Object.class);
testMethod(getProxyClass(), "run");
+
+ // Find a synthetic method in the dummy inner class. Do not print the name. Javac and Jack
+ // disagree on the naming of synthetic accessors.
+ testMethod(findSyntheticMethod(), NestedSynthetic.class, false);
}
private static Class<?> proxyClass = null;
@@ -54,8 +58,17 @@ public class Main {
private static void testMethod(Class<?> base, String methodName, Class<?>... types)
throws Exception {
Method m = base.getDeclaredMethod(methodName, types);
+ testMethod(m, base, true);
+ }
+
+ private static void testMethod(Method m, Class<?> base, boolean printName) {
String[] result = getMethodName(m);
- System.out.println(Arrays.toString(result));
+ if (!result[0].equals(m.getName())) {
+ throw new RuntimeException("Name not equal: " + m.getName() + " vs " + result[0]);
+ }
+ if (printName) {
+ System.out.println(Arrays.toString(result));
+ }
Class<?> declClass = getMethodDeclaringClass(m);
if (base != declClass) {
@@ -68,9 +81,67 @@ public class Main {
throw new RuntimeException("Modifiers not equal: " + m.getModifiers() + " vs " + modifiers);
}
System.out.println(modifiers);
+
+ System.out.print("Max locals: ");
+ try {
+ System.out.println(getMaxLocals(m));
+ } catch (RuntimeException e) {
+ System.out.println(e.getMessage());
+ }
+
+ System.out.print("Argument size: ");
+ try {
+ System.out.println(getArgumentsSize(m));
+ } catch (RuntimeException e) {
+ System.out.println(e.getMessage());
+ }
+
+ System.out.print("Location start: ");
+ try {
+ System.out.println(getMethodLocationStart(m));
+ } catch (RuntimeException e) {
+ System.out.println(e.getMessage());
+ }
+
+ System.out.print("Location end: ");
+ try {
+ System.out.println(getMethodLocationEnd(m));
+ } catch (RuntimeException e) {
+ System.out.println(e.getMessage());
+ }
+
+ System.out.println("Is native: " + isMethodNative(m));
+ System.out.println("Is obsolete: " + isMethodObsolete(m));
+ System.out.println("Is synthetic: " + isMethodSynthetic(m));
+ }
+
+ private static class NestedSynthetic {
+ // Accessing this private field will create a synthetic accessor method;
+ private static String dummy;
+ }
+
+ private static void dummyAccess() {
+ System.out.println(NestedSynthetic.dummy);
+ }
+
+ private static Method findSyntheticMethod() throws Exception {
+ Method methods[] = NestedSynthetic.class.getDeclaredMethods();
+ for (Method m : methods) {
+ if (m.isSynthetic()) {
+ return m;
+ }
+ }
+ throw new RuntimeException("Could not find synthetic method");
}
private static native String[] getMethodName(Method m);
private static native Class<?> getMethodDeclaringClass(Method m);
private static native int getMethodModifiers(Method m);
+ private static native int getMaxLocals(Method m);
+ private static native int getArgumentsSize(Method m);
+ private static native long getMethodLocationStart(Method m);
+ private static native long getMethodLocationEnd(Method m);
+ private static native boolean isMethodNative(Method m);
+ private static native boolean isMethodObsolete(Method m);
+ private static native boolean isMethodSynthetic(Method m);
}
diff --git a/test/911-get-stack-trace/stack_trace.cc b/test/911-get-stack-trace/stack_trace.cc
index 57f6a927ea..b3e8bc3b1f 100644
--- a/test/911-get-stack-trace/stack_trace.cc
+++ b/test/911-get-stack-trace/stack_trace.cc
@@ -63,6 +63,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace(
char* err;
jvmti_env->GetErrorName(result, &err);
printf("Failure running GetStackTrace: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
}
@@ -77,6 +78,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace(
char* err;
jvmti_env->GetErrorName(result2, &err);
printf("Failure running GetMethodName: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
}
@@ -94,6 +96,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace(
char* err;
jvmti_env->GetErrorName(line_result, &err);
printf("Failure running GetLineNumberTable: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
line_number_table = nullptr;
diff --git a/test/912-classes/classes.cc b/test/912-classes/classes.cc
index 838a92acf3..38a4f0e337 100644
--- a/test/912-classes/classes.cc
+++ b/test/912-classes/classes.cc
@@ -29,6 +29,20 @@
namespace art {
namespace Test912Classes {
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isModifiableClass(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jboolean res = JNI_FALSE;
+ jvmtiError result = jvmti_env->IsModifiableClass(klass, &res);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running IsModifiableClass: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return JNI_FALSE;
+ }
+ return res;
+}
+
extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassSignature(
JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
char* sig;
@@ -38,6 +52,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassSignature(
char* err;
jvmti_env->GetErrorName(result, &err);
printf("Failure running GetClassSignature: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return nullptr;
}
@@ -61,6 +76,154 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassSignature(
return ret;
}
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInterface(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jboolean is_interface = JNI_FALSE;
+ jvmtiError result = jvmti_env->IsInterface(klass, &is_interface);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running IsInterface: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return JNI_FALSE;
+ }
+ return is_interface;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isArrayClass(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jboolean is_array_class = JNI_FALSE;
+ jvmtiError result = jvmti_env->IsArrayClass(klass, &is_array_class);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running IsArrayClass: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return JNI_FALSE;
+ }
+ return is_array_class;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getClassModifiers(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jint mod;
+ jvmtiError result = jvmti_env->GetClassModifiers(klass, &mod);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetClassModifiers: %s\n", err);
+ return JNI_FALSE;
+ }
+ return mod;
+}
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassFields(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jint count = 0;
+ jfieldID* fields = nullptr;
+ jvmtiError result = jvmti_env->GetClassFields(klass, &count, &fields);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetClassFields: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return nullptr;
+ }
+
+ auto callback = [&](jint i) {
+ jint modifiers;
+ // Ignore any errors for simplicity.
+ jvmti_env->GetFieldModifiers(klass, fields[i], &modifiers);
+ constexpr jint kStatic = 0x8;
+ return env->ToReflectedField(klass,
+ fields[i],
+ (modifiers & kStatic) != 0 ? JNI_TRUE : JNI_FALSE);
+ };
+ jobjectArray ret = CreateObjectArray(env, count, "java/lang/Object", callback);
+ if (fields != nullptr) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(fields));
+ }
+ return ret;
+}
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassMethods(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jint count = 0;
+ jmethodID* methods = nullptr;
+ jvmtiError result = jvmti_env->GetClassMethods(klass, &count, &methods);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetClassMethods: %s\n", err);
+ return nullptr;
+ }
+
+ auto callback = [&](jint i) {
+ jint modifiers;
+ // Ignore any errors for simplicity.
+ jvmti_env->GetMethodModifiers(methods[i], &modifiers);
+ constexpr jint kStatic = 0x8;
+ return env->ToReflectedMethod(klass,
+ methods[i],
+ (modifiers & kStatic) != 0 ? JNI_TRUE : JNI_FALSE);
+ };
+ jobjectArray ret = CreateObjectArray(env, count, "java/lang/Object", callback);
+ if (methods != nullptr) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(methods));
+ }
+ return ret;
+}
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getImplementedInterfaces(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jint count = 0;
+ jclass* classes = nullptr;
+ jvmtiError result = jvmti_env->GetImplementedInterfaces(klass, &count, &classes);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetImplementedInterfaces: %s\n", err);
+ return nullptr;
+ }
+
+ auto callback = [&](jint i) {
+ return classes[i];
+ };
+ jobjectArray ret = CreateObjectArray(env, count, "java/lang/Class", callback);
+ if (classes != nullptr) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(classes));
+ }
+ return ret;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getClassStatus(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jint status;
+ jvmtiError result = jvmti_env->GetClassStatus(klass, &status);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetClassStatus: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return JNI_FALSE;
+ }
+ return status;
+}
+
+extern "C" JNIEXPORT jobject JNICALL Java_Main_getClassLoader(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jobject classloader;
+ jvmtiError result = jvmti_env->GetClassLoader(klass, &classloader);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetClassLoader: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return nullptr;
+ }
+ return classloader;
+}
+
// Don't do anything
jint OnLoad(JavaVM* vm,
char* options ATTRIBUTE_UNUSED,
diff --git a/test/912-classes/expected.txt b/test/912-classes/expected.txt
index 71b22f4d0b..44c861a3b7 100644
--- a/test/912-classes/expected.txt
+++ b/test/912-classes/expected.txt
@@ -1,7 +1,45 @@
[Ljava/lang/Object;, null]
+1
[Ljava/lang/String;, null]
+11
[Ljava/lang/Math;, null]
+11
[Ljava/util/List;, null]
+601
[L$Proxy0;, null]
+11
[I, null]
+411
[[D, null]
+411
+int interface=false array=false modifiable=false
+$Proxy0 interface=false array=false modifiable=false
+java.lang.Runnable interface=true array=false modifiable=false
+java.lang.String interface=false array=false modifiable=true
+[I interface=false array=true modifiable=false
+[Ljava.lang.Runnable; interface=false array=true modifiable=false
+[Ljava.lang.String; interface=false array=true modifiable=false
+[public static final int java.lang.Integer.BYTES, static final char[] java.lang.Integer.DigitOnes, static final char[] java.lang.Integer.DigitTens, public static final int java.lang.Integer.MAX_VALUE, public static final int java.lang.Integer.MIN_VALUE, public static final int java.lang.Integer.SIZE, private static final java.lang.String[] java.lang.Integer.SMALL_NEG_VALUES, private static final java.lang.String[] java.lang.Integer.SMALL_NONNEG_VALUES, public static final java.lang.Class java.lang.Integer.TYPE, static final char[] java.lang.Integer.digits, private static final long java.lang.Integer.serialVersionUID, static final int[] java.lang.Integer.sizeTable, private final int java.lang.Integer.value]
+[]
+[]
+[java.lang.Integer(), public java.lang.Integer(int), public java.lang.Integer(java.lang.String) throws java.lang.NumberFormatException, public static int java.lang.Integer.bitCount(int), public static int java.lang.Integer.compare(int,int), public static int java.lang.Integer.compareUnsigned(int,int), public static java.lang.Integer java.lang.Integer.decode(java.lang.String) throws java.lang.NumberFormatException, public static int java.lang.Integer.divideUnsigned(int,int), static int java.lang.Integer.formatUnsignedInt(int,int,char[],int,int), static void java.lang.Integer.getChars(int,int,char[]), public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String), public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String,int), public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String,java.lang.Integer), public static int java.lang.Integer.hashCode(int), public static int java.lang.Integer.highestOneBit(int), public static int java.lang.Integer.lowestOneBit(int), public static int java.lang.Integer.max(int,int), public static int java.lang.Integer.min(int,int), public static int java.lang.Integer.numberOfLeadingZeros(int), public static int java.lang.Integer.numberOfTrailingZeros(int), public static int java.lang.Integer.parseInt(java.lang.String) throws java.lang.NumberFormatException, public static int java.lang.Integer.parseInt(java.lang.String,int) throws java.lang.NumberFormatException, public static int java.lang.Integer.parseUnsignedInt(java.lang.String) throws java.lang.NumberFormatException, public static int java.lang.Integer.parseUnsignedInt(java.lang.String,int) throws java.lang.NumberFormatException, public static int java.lang.Integer.remainderUnsigned(int,int), public static int java.lang.Integer.reverse(int), public static int java.lang.Integer.reverseBytes(int), public static int java.lang.Integer.rotateLeft(int,int), public static int java.lang.Integer.rotateRight(int,int), public static int java.lang.Integer.signum(int), static int java.lang.Integer.stringSize(int), public static int java.lang.Integer.sum(int,int), public static java.lang.String java.lang.Integer.toBinaryString(int), public static java.lang.String java.lang.Integer.toHexString(int), public static java.lang.String java.lang.Integer.toOctalString(int), public static java.lang.String java.lang.Integer.toString(int), public static java.lang.String java.lang.Integer.toString(int,int), public static long java.lang.Integer.toUnsignedLong(int), public static java.lang.String java.lang.Integer.toUnsignedString(int), public static java.lang.String java.lang.Integer.toUnsignedString(int,int), private static java.lang.String java.lang.Integer.toUnsignedString0(int,int), public static java.lang.Integer java.lang.Integer.valueOf(int), public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String) throws java.lang.NumberFormatException, public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String,int) throws java.lang.NumberFormatException, public byte java.lang.Integer.byteValue(), public int java.lang.Integer.compareTo(java.lang.Integer), public int java.lang.Integer.compareTo(java.lang.Object), public double java.lang.Integer.doubleValue(), public boolean java.lang.Integer.equals(java.lang.Object), public float java.lang.Integer.floatValue(), public int java.lang.Integer.hashCode(), public int java.lang.Integer.intValue(), public long java.lang.Integer.longValue(), public short java.lang.Integer.shortValue(), public java.lang.String java.lang.Integer.toString()]
+[]
+[]
+int 100000
+class [Ljava.lang.String; 10000
+class java.lang.Object 111
+class Main$TestForNonInit 11
+class Main$TestForInitFail 1001
+int []
+class [Ljava.lang.String; []
+class java.lang.Object []
+interface Main$InfA []
+interface Main$InfB [interface Main$InfA]
+interface Main$InfC [interface Main$InfB]
+class Main$ClassA [interface Main$InfA]
+class Main$ClassB [interface Main$InfB]
+class Main$ClassC [interface Main$InfA, interface Main$InfC]
+class java.lang.String null
+class [Ljava.lang.String; null
+interface Main$InfA dalvik.system.PathClassLoader
+class $Proxy0 dalvik.system.PathClassLoader
diff --git a/test/912-classes/src/Main.java b/test/912-classes/src/Main.java
index 025584ec0a..e627d4227a 100644
--- a/test/912-classes/src/Main.java
+++ b/test/912-classes/src/Main.java
@@ -34,6 +34,48 @@ public class Main {
testClass(int.class);
testClass(double[].class);
+
+ testClassType(int.class);
+ testClassType(getProxyClass());
+ testClassType(Runnable.class);
+ testClassType(String.class);
+
+ testClassType(int[].class);
+ testClassType(Runnable[].class);
+ testClassType(String[].class);
+
+ testClassFields(Integer.class);
+ testClassFields(int.class);
+ testClassFields(String[].class);
+
+ testClassMethods(Integer.class);
+ testClassMethods(int.class);
+ testClassMethods(String[].class);
+
+ testClassStatus(int.class);
+ testClassStatus(String[].class);
+ testClassStatus(Object.class);
+ testClassStatus(TestForNonInit.class);
+ try {
+ System.out.println(TestForInitFail.dummy);
+ } catch (ExceptionInInitializerError e) {
+ }
+ testClassStatus(TestForInitFail.class);
+
+ testInterfaces(int.class);
+ testInterfaces(String[].class);
+ testInterfaces(Object.class);
+ testInterfaces(InfA.class);
+ testInterfaces(InfB.class);
+ testInterfaces(InfC.class);
+ testInterfaces(ClassA.class);
+ testInterfaces(ClassB.class);
+ testInterfaces(ClassC.class);
+
+ testClassLoader(String.class);
+ testClassLoader(String[].class);
+ testClassLoader(InfA.class);
+ testClassLoader(getProxyClass());
}
private static Class<?> proxyClass = null;
@@ -55,7 +97,95 @@ public class Main {
private static void testClass(Class<?> base) throws Exception {
String[] result = getClassSignature(base);
System.out.println(Arrays.toString(result));
+ int mod = getClassModifiers(base);
+ if (mod != base.getModifiers()) {
+ throw new RuntimeException("Unexpected modifiers: " + base.getModifiers() + " vs " + mod);
+ }
+ System.out.println(Integer.toHexString(mod));
+ }
+
+ private static void testClassType(Class<?> c) throws Exception {
+ boolean isInterface = isInterface(c);
+ boolean isArray = isArrayClass(c);
+ boolean isModifiable = isModifiableClass(c);
+ System.out.println(c.getName() + " interface=" + isInterface + " array=" + isArray +
+ " modifiable=" + isModifiable);
+ }
+
+ private static void testClassFields(Class<?> c) throws Exception {
+ System.out.println(Arrays.toString(getClassFields(c)));
+ }
+
+ private static void testClassMethods(Class<?> c) throws Exception {
+ System.out.println(Arrays.toString(getClassMethods(c)));
+ }
+
+ private static void testClassStatus(Class<?> c) {
+ System.out.println(c + " " + Integer.toBinaryString(getClassStatus(c)));
+ }
+
+ private static void testInterfaces(Class<?> c) {
+ System.out.println(c + " " + Arrays.toString(getImplementedInterfaces(c)));
+ }
+
+ private static boolean IsBootClassLoader(ClassLoader l) {
+ // Hacky check for Android's fake boot classloader.
+ return l.getClass().getName().equals("java.lang.BootClassLoader");
}
+ private static void testClassLoader(Class<?> c) {
+ Object cl = getClassLoader(c);
+ System.out.println(c + " " + (cl != null ? cl.getClass().getName() : "null"));
+ if (cl == null) {
+ if (c.getClassLoader() != null && !IsBootClassLoader(c.getClassLoader())) {
+ throw new RuntimeException("Expected " + c.getClassLoader() + ", but got null.");
+ }
+ } else {
+ if (!(cl instanceof ClassLoader)) {
+ throw new RuntimeException("Unexpected \"classloader\": " + cl + " (" + cl.getClass() +
+ ")");
+ }
+ if (cl != c.getClassLoader()) {
+ throw new RuntimeException("Unexpected classloader: " + c.getClassLoader() + " vs " + cl);
+ }
+ }
+ }
+
+ private static native boolean isModifiableClass(Class<?> c);
private static native String[] getClassSignature(Class<?> c);
+
+ private static native boolean isInterface(Class<?> c);
+ private static native boolean isArrayClass(Class<?> c);
+
+ private static native int getClassModifiers(Class<?> c);
+
+ private static native Object[] getClassFields(Class<?> c);
+ private static native Object[] getClassMethods(Class<?> c);
+ private static native Class[] getImplementedInterfaces(Class<?> c);
+
+ private static native int getClassStatus(Class<?> c);
+
+ private static native Object getClassLoader(Class<?> c);
+
+ private static class TestForNonInit {
+ public static double dummy = Math.random(); // So it can't be compile-time initialized.
+ }
+
+ private static class TestForInitFail {
+ public static int dummy = ((int)Math.random())/0; // So it throws when initializing.
+ }
+
+ public static interface InfA {
+ }
+ public static interface InfB extends InfA {
+ }
+ public static interface InfC extends InfB {
+ }
+
+ public abstract static class ClassA implements InfA {
+ }
+ public abstract static class ClassB extends ClassA implements InfB {
+ }
+ public abstract static class ClassC implements InfA, InfC {
+ }
}
diff --git a/test/913-heaps/heaps.cc b/test/913-heaps/heaps.cc
index 49ab7dd83e..0b232af0df 100644
--- a/test/913-heaps/heaps.cc
+++ b/test/913-heaps/heaps.cc
@@ -49,6 +49,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_forceGarbageCollection(JNIEnv* env A
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Error forcing a garbage collection: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
}
}
@@ -106,6 +107,7 @@ static bool Run(jint heap_filter,
char* err;
jvmti_env->GetErrorName(ret, &err);
printf("Failure running FollowReferences: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
return false;
}
return true;
diff --git a/test/918-fields/build b/test/918-fields/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/918-fields/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/918-fields/expected.txt b/test/918-fields/expected.txt
new file mode 100644
index 0000000000..39d3e70550
--- /dev/null
+++ b/test/918-fields/expected.txt
@@ -0,0 +1,16 @@
+[PI, D, null]
+class java.lang.Math
+25
+false
+[value, I, null]
+class java.lang.Integer
+18
+false
+[this$0, LMain;, null]
+class Main$Foo
+4112
+true
+[VAL, I, null]
+interface Main$Bar
+25
+false
diff --git a/test/918-fields/fields.cc b/test/918-fields/fields.cc
new file mode 100644
index 0000000000..4d2b34b94e
--- /dev/null
+++ b/test/918-fields/fields.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 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 "fields.h"
+
+#include <stdio.h>
+
+#include "base/macros.h"
+#include "jni.h"
+#include "openjdkjvmti/jvmti.h"
+#include "ScopedLocalRef.h"
+
+#include "ti-agent/common_helper.h"
+#include "ti-agent/common_load.h"
+
+namespace art {
+namespace Test918Fields {
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getFieldName(
+ JNIEnv* env, jclass klass, jobject field) {
+ jfieldID id = env->FromReflectedField(field);
+
+ char* name;
+ char* sig;
+ char* gen;
+ // Note: technically putting the caller class here is wrong, but we don't need it, anyways.
+ jvmtiError result = jvmti_env->GetFieldName(klass, id, &name, &sig, &gen);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetFieldName: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return nullptr;
+ }
+
+ auto callback = [&](jint i) {
+ if (i == 0) {
+ return name == nullptr ? nullptr : env->NewStringUTF(name);
+ } else if (i == 1) {
+ return sig == nullptr ? nullptr : env->NewStringUTF(sig);
+ } else {
+ return gen == nullptr ? nullptr : env->NewStringUTF(gen);
+ }
+ };
+ jobjectArray ret = CreateObjectArray(env, 3, "java/lang/String", callback);
+
+ // Need to deallocate the strings.
+ if (name != nullptr) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name));
+ }
+ if (sig != nullptr) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(sig));
+ }
+ if (gen != nullptr) {
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(gen));
+ }
+
+ // Also run GetMethodName with all parameter pointers null to check for segfaults.
+ jvmtiError result2 = jvmti_env->GetFieldName(klass, id, nullptr, nullptr, nullptr);
+ if (result2 != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result2, &err);
+ printf("Failure running GetFieldName(null, null, null): %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return nullptr;
+ }
+
+ return ret;
+}
+
+extern "C" JNIEXPORT jclass JNICALL Java_Main_getFieldDeclaringClass(
+ JNIEnv* env, jclass klass, jobject field) {
+ jfieldID id = env->FromReflectedField(field);
+
+ jclass declaring_class;
+ jvmtiError result = jvmti_env->GetFieldDeclaringClass(klass, id, &declaring_class);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetFieldDeclaringClass: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return nullptr;
+ }
+
+ return declaring_class;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getFieldModifiers(
+ JNIEnv* env, jclass klass, jobject field) {
+ jfieldID id = env->FromReflectedField(field);
+
+ jint modifiers;
+ jvmtiError result = jvmti_env->GetFieldModifiers(klass, id, &modifiers);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetFieldModifiers: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return 0;
+ }
+
+ return modifiers;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isFieldSynthetic(
+ JNIEnv* env, jclass klass, jobject field) {
+ jfieldID id = env->FromReflectedField(field);
+
+ jboolean synth;
+ jvmtiError result = jvmti_env->IsFieldSynthetic(klass, id, &synth);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running IsFieldSynthetic: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return 0;
+ }
+
+ return synth;
+}
+
+// Don't do anything
+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);
+ return 0;
+}
+
+} // namespace Test918Fields
+} // namespace art
diff --git a/test/918-fields/fields.h b/test/918-fields/fields.h
new file mode 100644
index 0000000000..89bd1614d5
--- /dev/null
+++ b/test/918-fields/fields.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_918_FIELDS_FIELDS_H_
+#define ART_TEST_918_FIELDS_FIELDS_H_
+
+#include <jni.h>
+
+namespace art {
+namespace Test918Fields {
+
+jint OnLoad(JavaVM* vm, char* options, void* reserved);
+
+} // namespace Test918Fields
+} // namespace art
+
+#endif // ART_TEST_918_FIELDS_FIELDS_H_
diff --git a/test/918-fields/info.txt b/test/918-fields/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/918-fields/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/918-fields/run b/test/918-fields/run
new file mode 100755
index 0000000000..4379349cb2
--- /dev/null
+++ b/test/918-fields/run
@@ -0,0 +1,19 @@
+#!/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 "$@" --experimental agents \
+ --experimental runtime-plugins \
+ --jvmti
diff --git a/test/918-fields/src/Main.java b/test/918-fields/src/Main.java
new file mode 100644
index 0000000000..8af6e7b375
--- /dev/null
+++ b/test/918-fields/src/Main.java
@@ -0,0 +1,70 @@
+/*
+ * 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.Field;
+import java.util.Arrays;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[1]);
+
+ doTest();
+ }
+
+ public static void doTest() throws Exception {
+ testField(Math.class, "PI");
+ testField(Integer.class, "value");
+ testField(Foo.class, "this$0");
+ testField(Bar.class, "VAL");
+ }
+
+ private static void testField(Class<?> base, String fieldName)
+ throws Exception {
+ Field f = base.getDeclaredField(fieldName);
+ String[] result = getFieldName(f);
+ System.out.println(Arrays.toString(result));
+
+ Class<?> declClass = getFieldDeclaringClass(f);
+ if (base != declClass) {
+ throw new RuntimeException("Declaring class not equal: " + base + " vs " + declClass);
+ }
+ System.out.println(declClass);
+
+ int modifiers = getFieldModifiers(f);
+ if (modifiers != f.getModifiers()) {
+ throw new RuntimeException("Modifiers not equal: " + f.getModifiers() + " vs " + modifiers);
+ }
+ System.out.println(modifiers);
+
+ boolean synth = isFieldSynthetic(f);
+ if (synth != f.isSynthetic()) {
+ throw new RuntimeException("Synthetic not equal: " + f.isSynthetic() + " vs " + synth);
+ }
+ System.out.println(synth);
+ }
+
+ private static native String[] getFieldName(Field f);
+ private static native Class<?> getFieldDeclaringClass(Field f);
+ private static native int getFieldModifiers(Field f);
+ private static native boolean isFieldSynthetic(Field f);
+
+ private class Foo {
+ }
+
+ private static interface Bar {
+ public static int VAL = 1;
+ }
+}
diff --git a/test/919-obsolete-fields/build b/test/919-obsolete-fields/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/919-obsolete-fields/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/919-obsolete-fields/expected.txt b/test/919-obsolete-fields/expected.txt
new file mode 100644
index 0000000000..4caefc6200
--- /dev/null
+++ b/test/919-obsolete-fields/expected.txt
@@ -0,0 +1,21 @@
+Pre Start private method call
+hello - private
+Post Start private method call
+Not doing anything here
+Pre Finish private method call
+goodbye - private
+Post Finish private method call
+Pre Start private method call
+hello - private
+Post Start private method call
+transforming calling function
+Pre Finish private method call
+Goodbye - private - Transformed
+Post Finish private method call
+pre Start private method call - Transformed
+Hello - private - Transformed
+post Start private method call - Transformed
+Not doing anything here
+pre Finish private method call - Transformed
+Goodbye - private - Transformed
+post Finish private method call - Transformed
diff --git a/test/919-obsolete-fields/info.txt b/test/919-obsolete-fields/info.txt
new file mode 100644
index 0000000000..97739cabbd
--- /dev/null
+++ b/test/919-obsolete-fields/info.txt
@@ -0,0 +1 @@
+Tests obsolete method field access support
diff --git a/test/919-obsolete-fields/run b/test/919-obsolete-fields/run
new file mode 100755
index 0000000000..4379349cb2
--- /dev/null
+++ b/test/919-obsolete-fields/run
@@ -0,0 +1,19 @@
+#!/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 "$@" --experimental agents \
+ --experimental runtime-plugins \
+ --jvmti
diff --git a/test/919-obsolete-fields/src/Main.java b/test/919-obsolete-fields/src/Main.java
new file mode 100644
index 0000000000..895c7a3fa4
--- /dev/null
+++ b/test/919-obsolete-fields/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.function.Consumer;
+import java.util.Base64;
+
+public class Main {
+
+ // What follows is the base64 encoded representation of the following class:
+ //
+ // import java.util.function.Consumer;
+ //
+ // class Transform {
+ // private Consumer<String> reporter;
+ // public Transform(Consumer<String> reporter) {
+ // this.reporter = reporter;
+ // }
+ //
+ // private void Start() {
+ // reporter.accept("Hello - private - Transformed");
+ // }
+ //
+ // private void Finish() {
+ // reporter.accept("Goodbye - private - Transformed");
+ // }
+ //
+ // public void sayHi(Runnable r) {
+ // reporter.accept("pre Start private method call - Transformed");
+ // Start();
+ // reporter.accept("post Start private method call - Transformed");
+ // r.run();
+ // reporter.accept("pre Finish private method call - Transformed");
+ // Finish();
+ // reporter.accept("post Finish private method call - Transformed");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQANAoADgAfCQANACAIACELACIAIwgAJAgAJQoADQAmCAAnCwAoACkIACoKAA0AKwgA" +
+ "LAcALQcALgEACHJlcG9ydGVyAQAdTGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjsBAAlTaWdu" +
+ "YXR1cmUBADFMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyPExqYXZhL2xhbmcvU3RyaW5nOz47" +
+ "AQAGPGluaXQ+AQAgKExqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7KVYBAARDb2RlAQAPTGlu" +
+ "ZU51bWJlclRhYmxlAQA0KExqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI8TGphdmEvbGFuZy9T" +
+ "dHJpbmc7PjspVgEABVN0YXJ0AQADKClWAQAGRmluaXNoAQAFc2F5SGkBABcoTGphdmEvbGFuZy9S" +
+ "dW5uYWJsZTspVgEAClNvdXJjZUZpbGUBAA5UcmFuc2Zvcm0uamF2YQwAEwAZDAAPABABAB1IZWxs" +
+ "byAtIHByaXZhdGUgLSBUcmFuc2Zvcm1lZAcALwwAMAAxAQAfR29vZGJ5ZSAtIHByaXZhdGUgLSBU" +
+ "cmFuc2Zvcm1lZAEAK3ByZSBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQM" +
+ "ABgAGQEALHBvc3QgU3RhcnQgcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkBwAyDAAz" +
+ "ABkBACxwcmUgRmluaXNoIHByaXZhdGUgbWV0aG9kIGNhbGwgLSBUcmFuc2Zvcm1lZAwAGgAZAQAt" +
+ "cG9zdCBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkAQAJVHJhbnNmb3Jt" +
+ "AQAQamF2YS9sYW5nL09iamVjdAEAG2phdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcgEABmFjY2Vw" +
+ "dAEAFShMamF2YS9sYW5nL09iamVjdDspVgEAEmphdmEvbGFuZy9SdW5uYWJsZQEAA3J1bgAgAA0A" +
+ "DgAAAAEAAgAPABAAAQARAAAAAgASAAQAAQATABQAAgAVAAAAKgACAAIAAAAKKrcAASortQACsQAA" +
+ "AAEAFgAAAA4AAwAAABUABAAWAAkAFwARAAAAAgAXAAIAGAAZAAEAFQAAACgAAgABAAAADCq0AAIS" +
+ "A7kABAIAsQAAAAEAFgAAAAoAAgAAABoACwAbAAIAGgAZAAEAFQAAACgAAgABAAAADCq0AAISBbkA" +
+ "BAIAsQAAAAEAFgAAAAoAAgAAAB4ACwAfAAEAGwAcAAEAFQAAAG8AAgACAAAAOyq0AAISBrkABAIA" +
+ "KrcAByq0AAISCLkABAIAK7kACQEAKrQAAhIKuQAEAgAqtwALKrQAAhIMuQAEAgCxAAAAAQAWAAAA" +
+ "IgAIAAAAIgALACMADwAkABoAJQAgACYAKwAnAC8AKAA6ACkAAQAdAAAAAgAe");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQAw/b59wCwTlSVDmuhPEezuK3oe0rtT4ujMBQAAcAAAAHhWNBIAAAAAAAAAAAgFAAAd" +
+ "AAAAcAAAAAYAAADkAAAABAAAAPwAAAABAAAALAEAAAcAAAA0AQAAAQAAAGwBAABABAAAjAEAAJoC" +
+ "AACdAgAAoAIAAKgCAACsAgAAsgIAALoCAADbAgAA+gIAAAcDAAAmAwAAOgMAAFADAABkAwAAggMA" +
+ "AKEDAACoAwAAuAMAALsDAAC/AwAAxwMAANsDAAAKBAAAOAQAAGYEAACTBAAAnQQAAKIEAACpBAAA" +
+ "CAAAAAkAAAAKAAAACwAAAA4AAAARAAAAEQAAAAUAAAAAAAAAEgAAAAUAAACEAgAAEgAAAAUAAACM" +
+ "AgAAEgAAAAUAAACUAgAAAAAEABkAAAAAAAMAAgAAAAAAAAAFAAAAAAAAAA8AAAAAAAIAGwAAAAIA" +
+ "AAACAAAAAwAAABoAAAAEAAEAEwAAAAAAAAAAAAAAAgAAAAAAAAAQAAAAZAIAAO8EAAAAAAAAAQAA" +
+ "ANEEAAABAAAA3wQAAAIAAgABAAAAsAQAAAYAAABwEAQAAABbAQAADgADAAEAAgAAALgEAAAJAAAA" +
+ "VCAAABsBBgAAAHIgBgAQAA4AAAADAAEAAgAAAL4EAAAJAAAAVCAAABsBBwAAAHIgBgAQAA4AAAAE" +
+ "AAIAAgAAAMQEAAAqAAAAVCAAABsBGAAAAHIgBgAQAHAQAgACAFQgAAAbARYAAAByIAYAEAByEAUA" +
+ "AwBUIAAAGwEXAAAAciAGABAAcBABAAIAVCAAABsBFQAAAHIgBgAQAA4AAAAAAAEAAAABAAAAAAAA" +
+ "AAAAAACMAQAAAAAAAJQBAAABAAAAAgAAAAEAAAADAAAAAQAAAAQAASgAATwABjxpbml0PgACPjsA" +
+ "BD47KVYABkZpbmlzaAAfR29vZGJ5ZSAtIHByaXZhdGUgLSBUcmFuc2Zvcm1lZAAdSGVsbG8gLSBw" +
+ "cml2YXRlIC0gVHJhbnNmb3JtZWQAC0xUcmFuc2Zvcm07AB1MZGFsdmlrL2Fubm90YXRpb24vU2ln" +
+ "bmF0dXJlOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9sYW5nL1J1bm5hYmxlOwASTGphdmEv" +
+ "bGFuZy9TdHJpbmc7ABxMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAB1MamF2YS91dGlsL2Z1" +
+ "bmN0aW9uL0NvbnN1bWVyOwAFU3RhcnQADlRyYW5zZm9ybS5qYXZhAAFWAAJWTAAGYWNjZXB0ABJl" +
+ "bWl0dGVyOiBqYWNrLTQuMTkALXBvc3QgRmluaXNoIHByaXZhdGUgbWV0aG9kIGNhbGwgLSBUcmFu" +
+ "c2Zvcm1lZAAscG9zdCBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQALHBy" +
+ "ZSBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkACtwcmUgU3RhcnQgcHJp" +
+ "dmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkAAhyZXBvcnRlcgADcnVuAAVzYXlIaQAFdmFs" +
+ "dWUAFQEABw48LQAeAAcOhwAaAAcOhwAiAQAHDoc8hzyHPIcAAgEBHBwEFw0XARcMFwMCAQEcHAUX" +
+ "ABcNFwEXDBcEAAEDAQACAIGABJwDAQK4AwEC3AMDAYAEABAAAAAAAAAAAQAAAAAAAAABAAAAHQAA" +
+ "AHAAAAACAAAABgAAAOQAAAADAAAABAAAAPwAAAAEAAAAAQAAACwBAAAFAAAABwAAADQBAAAGAAAA" +
+ "AQAAAGwBAAADEAAAAgAAAIwBAAABIAAABAAAAJwBAAAGIAAAAQAAAGQCAAABEAAAAwAAAIQCAAAC" +
+ "IAAAHQAAAJoCAAADIAAABAAAALAEAAAEIAAAAgAAANEEAAAAIAAAAQAAAO8EAAAAEAAAAQAAAAgF" +
+ "AAA=");
+
+ // 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 static void main(String[] args) {
+ System.loadLibrary(args[1]);
+ TestWatcher w = new TestWatcher();
+ 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;
+
+ public static void doTest(Transform t, TestWatcher w) {
+ Runnable do_redefinition = () -> {
+ w.accept("transforming calling function");
+ doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ };
+ // This just prints something out to show we are running the Runnable.
+ Runnable say_nothing = () -> { w.accept("Not doing anything here"); };
+
+ // Try and redefine.
+ t.sayHi(say_nothing);
+ t.sayHi(do_redefinition);
+ t.sayHi(say_nothing);
+
+ // Print output of last run.
+ System.out.print(w.getOutput());
+ }
+
+ // Transforms the class
+ private static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+}
diff --git a/test/919-obsolete-fields/src/Transform.java b/test/919-obsolete-fields/src/Transform.java
new file mode 100644
index 0000000000..abd1d19b66
--- /dev/null
+++ b/test/919-obsolete-fields/src/Transform.java
@@ -0,0 +1,47 @@
+/*
+ * 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 {
+ private Consumer<String> reporter;
+ public Transform(Consumer<String> reporter) {
+ this.reporter = reporter;
+ }
+
+ private void Start() {
+ reporter.accept("hello - private");
+ }
+
+ private void Finish() {
+ reporter.accept("goodbye - private");
+ }
+
+ public void sayHi(Runnable r) {
+ 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);
+ reporter.accept("Pre Finish private method call");
+ Finish();
+ reporter.accept("Post Finish private method call");
+ }
+}
diff --git a/test/920-objects/build b/test/920-objects/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/920-objects/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/920-objects/expected.txt b/test/920-objects/expected.txt
new file mode 100644
index 0000000000..80feeb93e4
--- /dev/null
+++ b/test/920-objects/expected.txt
@@ -0,0 +1,10 @@
+class java.lang.Object 8
+class java.lang.Object 8
+class [I 12
+class [I 16
+class [I 20
+class [D 16
+class [D 24
+class [D 32
+class java.lang.String 24
+class java.lang.String 24
diff --git a/test/920-objects/info.txt b/test/920-objects/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/920-objects/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/920-objects/objects.cc b/test/920-objects/objects.cc
new file mode 100644
index 0000000000..886dd0e673
--- /dev/null
+++ b/test/920-objects/objects.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 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 "objects.h"
+
+#include <stdio.h>
+
+#include "base/macros.h"
+#include "jni.h"
+#include "openjdkjvmti/jvmti.h"
+#include "ScopedLocalRef.h"
+
+#include "ti-agent/common_helper.h"
+#include "ti-agent/common_load.h"
+
+namespace art {
+namespace Test920Objects {
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_getObjectSize(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass klass ATTRIBUTE_UNUSED, jobject object) {
+ jlong size;
+
+ jvmtiError result = jvmti_env->GetObjectSize(object, &size);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetObjectSize: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return -1;
+ }
+
+ return size;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getObjectHashCode(
+ JNIEnv* env ATTRIBUTE_UNUSED, jclass klass ATTRIBUTE_UNUSED, jobject object) {
+ jint hash;
+
+ jvmtiError result = jvmti_env->GetObjectHashCode(object, &hash);
+ if (result != JVMTI_ERROR_NONE) {
+ char* err;
+ jvmti_env->GetErrorName(result, &err);
+ printf("Failure running GetObjectHashCode: %s\n", err);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return -1;
+ }
+
+ return hash;
+}
+
+// Don't do anything
+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);
+ return 0;
+}
+
+} // namespace Test920Objects
+} // namespace art
diff --git a/test/920-objects/objects.h b/test/920-objects/objects.h
new file mode 100644
index 0000000000..5f21e7b7cb
--- /dev/null
+++ b/test/920-objects/objects.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_920_OBJECTS_OBJECTS_H_
+#define ART_TEST_920_OBJECTS_OBJECTS_H_
+
+#include <jni.h>
+
+namespace art {
+namespace Test920Objects {
+
+jint OnLoad(JavaVM* vm, char* options, void* reserved);
+
+} // namespace Test920Objects
+} // namespace art
+
+#endif // ART_TEST_920_OBJECTS_OBJECTS_H_
diff --git a/test/920-objects/run b/test/920-objects/run
new file mode 100755
index 0000000000..4379349cb2
--- /dev/null
+++ b/test/920-objects/run
@@ -0,0 +1,19 @@
+#!/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 "$@" --experimental agents \
+ --experimental runtime-plugins \
+ --jvmti
diff --git a/test/920-objects/src/Main.java b/test/920-objects/src/Main.java
new file mode 100644
index 0000000000..5dbe1a7e58
--- /dev/null
+++ b/test/920-objects/src/Main.java
@@ -0,0 +1,98 @@
+/*
+ * 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.Field;
+import java.util.Arrays;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[1]);
+
+ doTest();
+ }
+
+ public static void doTest() throws Exception {
+ testObjectSize(new Object());
+ testObjectSize(new Object());
+
+ testObjectSize(new int[0]);
+ testObjectSize(new int[1]);
+ testObjectSize(new int[2]);
+
+ testObjectSize(new double[0]);
+ testObjectSize(new double[1]);
+ testObjectSize(new double[2]);
+
+ testObjectSize(new String("abc"));
+ testObjectSize(new String("wxyz"));
+
+ testObjectHash();
+ }
+
+ private static void testObjectSize(Object o) {
+ System.out.println(o.getClass() + " " + getObjectSize(o));
+ }
+
+ private static void testObjectHash() {
+ Object[] objects = new Object[] {
+ new Object(),
+ new Object(),
+
+ new MyHash(1),
+ new MyHash(1),
+ new MyHash(2)
+ };
+
+ int hashes[] = new int[objects.length];
+
+ for (int i = 0; i < objects.length; i++) {
+ hashes[i] = getObjectHashCode(objects[i]);
+ }
+
+ // Implementation detail: we use the identity hashcode, for simplicity.
+ for (int i = 0; i < objects.length; i++) {
+ int ihash = System.identityHashCode(objects[i]);
+ if (hashes[i] != ihash) {
+ throw new RuntimeException(objects[i] + ": " + hashes[i] + " vs " + ihash);
+ }
+ }
+
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
+ for (int i = 0; i < objects.length; i++) {
+ int newhash = getObjectHashCode(objects[i]);
+ if (hashes[i] != newhash) {
+ throw new RuntimeException(objects[i] + ": " + hashes[i] + " vs " + newhash);
+ }
+ }
+ }
+
+ private static native long getObjectSize(Object o);
+ private static native int getObjectHashCode(Object o);
+
+ private static class MyHash {
+ private int hash;
+
+ public MyHash(int h) {
+ hash = h;
+ }
+
+ public int hashCode() {
+ return hash;
+ }
+ }
+}
diff --git a/test/921-hello-failure/build b/test/921-hello-failure/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/921-hello-failure/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/921-hello-failure/expected.txt b/test/921-hello-failure/expected.txt
new file mode 100644
index 0000000000..e2665ef30b
--- /dev/null
+++ b/test/921-hello-failure/expected.txt
@@ -0,0 +1,15 @@
+hello - NewName
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform;> due to JVMTI_ERROR_NAMES_DONT_MATCH)
+hello - NewName
+hello - DifferentAccess
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED)
+hello - DifferentAccess
+hello2 - NewInterface
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform2;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED)
+hello2 - NewInterface
+hello2 - MissingInterface
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform2;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED)
+hello2 - MissingInterface
+hello2 - ReorderInterface
+Transformation error : java.lang.Exception(Failed to redefine class <LTransform2;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED)
+hello2 - ReorderInterface
diff --git a/test/921-hello-failure/info.txt b/test/921-hello-failure/info.txt
new file mode 100644
index 0000000000..9d241c77b1
--- /dev/null
+++ b/test/921-hello-failure/info.txt
@@ -0,0 +1,7 @@
+Tests for redefinition failure modes.
+
+Tests
+----
+
+- NewName: The name of the class is changed
+- DifferentAccess: Class access is changed from <default> to 'public'
diff --git a/test/921-hello-failure/run b/test/921-hello-failure/run
new file mode 100755
index 0000000000..3ef4832da2
--- /dev/null
+++ b/test/921-hello-failure/run
@@ -0,0 +1,20 @@
+#!/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 "$@" --experimental agents \
+ --experimental runtime-plugins \
+ --jvmti
diff --git a/test/921-hello-failure/src/DifferentAccess.java b/test/921-hello-failure/src/DifferentAccess.java
new file mode 100644
index 0000000000..d4b16e0522
--- /dev/null
+++ b/test/921-hello-failure/src/DifferentAccess.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 DifferentAccess {
+ // The following is a base64 encoding of the following class.
+ // public class NotTransform {
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFQoABgAPBwAQCAARCgACABIHABMHABQBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP" +
+ "TGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3VyY2VG" +
+ "aWxlAQAOVHJhbnNmb3JtLmphdmEMAAcACAEAD2phdmEvbGFuZy9FcnJvcgEAFVNob3VsZCBub3Qg" +
+ "YmUgY2FsbGVkIQwABwAMAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAAhAAUABgAAAAAA" +
+ "AgABAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAEAAQALAAwAAQAJAAAA" +
+ "IgADAAIAAAAKuwACWRIDtwAEvwAAAAEACgAAAAYAAQAAAAMAAQANAAAAAgAO");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQANVRT7zleRLG4E5DhtK7OtoDxZlUQMI5eQAgAAcAAAAHhWNBIAAAAAAAAAAPwBAAAL" +
+ "AAAAcAAAAAUAAACcAAAAAgAAALAAAAAAAAAAAAAAAAQAAADIAAAAAQAAAOgAAACIAQAACAEAAEoB" +
+ "AABSAQAAXwEAAHIBAACGAQAAmgEAALEBAADBAQAAxAEAAMgBAADcAQAAAQAAAAIAAAADAAAABAAA" +
+ "AAcAAAAHAAAABAAAAAAAAAAIAAAABAAAAEQBAAAAAAAAAAAAAAAAAQAKAAAAAQABAAAAAAACAAAA" +
+ "AAAAAAAAAAABAAAAAgAAAAAAAAAGAAAAAAAAAO4BAAAAAAAAAQABAAEAAADjAQAABAAAAHAQAwAA" +
+ "AA4ABAACAAIAAADoAQAACQAAACIAAQAbAQUAAABwIAIAEAAnAAAAAQAAAAMABjxpbml0PgALTFRy" +
+ "YW5zZm9ybTsAEUxqYXZhL2xhbmcvRXJyb3I7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xh" +
+ "bmcvU3RyaW5nOwAVU2hvdWxkIG5vdCBiZSBjYWxsZWQhAA5UcmFuc2Zvcm0uamF2YQABVgACVkwA" +
+ "EmVtaXR0ZXI6IGphY2stNC4yMAAFc2F5SGkAAQAHDgADAQAHDgAAAAEBAIGABIgCAQGgAgwAAAAA" +
+ "AAAAAQAAAAAAAAABAAAACwAAAHAAAAACAAAABQAAAJwAAAADAAAAAgAAALAAAAAFAAAABAAAAMgA" +
+ "AAAGAAAAAQAAAOgAAAABIAAAAgAAAAgBAAABEAAAAQAAAEQBAAACIAAACwAAAEoBAAADIAAAAgAA" +
+ "AOMBAAAAIAAAAQAAAO4BAAAAEAAAAQAAAPwBAAA=");
+
+ public static void doTest(Transform t) {
+ t.sayHi("DifferentAccess");
+ try {
+ Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("DifferentAccess");
+ }
+}
diff --git a/test/921-hello-failure/src/Iface1.java b/test/921-hello-failure/src/Iface1.java
new file mode 100644
index 0000000000..f53275a656
--- /dev/null
+++ b/test/921-hello-failure/src/Iface1.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.
+ */
+
+interface Iface1 {
+ void sayHi(String s);
+}
diff --git a/test/921-hello-failure/src/Iface2.java b/test/921-hello-failure/src/Iface2.java
new file mode 100644
index 0000000000..54cdd901c9
--- /dev/null
+++ b/test/921-hello-failure/src/Iface2.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.
+ */
+
+interface Iface2 {
+ void sayHi(String s);
+}
diff --git a/test/921-hello-failure/src/Iface3.java b/test/921-hello-failure/src/Iface3.java
new file mode 100644
index 0000000000..819134d30d
--- /dev/null
+++ b/test/921-hello-failure/src/Iface3.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.
+ */
+
+interface Iface3 {
+ void sayHi(String s);
+}
diff --git a/test/921-hello-failure/src/Main.java b/test/921-hello-failure/src/Main.java
new file mode 100644
index 0000000000..69c48e26cc
--- /dev/null
+++ b/test/921-hello-failure/src/Main.java
@@ -0,0 +1,32 @@
+/*
+ * 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 {
+
+ public static void main(String[] args) {
+ System.loadLibrary(args[1]);
+ NewName.doTest(new Transform());
+ DifferentAccess.doTest(new Transform());
+ NewInterface.doTest(new Transform2());
+ MissingInterface.doTest(new Transform2());
+ ReorderInterface.doTest(new Transform2());
+ }
+
+ // Transforms the class. This throws an exception if something goes wrong.
+ public static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile) throws Exception;
+}
diff --git a/test/921-hello-failure/src/MissingInterface.java b/test/921-hello-failure/src/MissingInterface.java
new file mode 100644
index 0000000000..d17a6defbe
--- /dev/null
+++ b/test/921-hello-failure/src/MissingInterface.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 MissingInterface {
+ // The following is a base64 encoding of the following class.
+ // class Transform2 implements Iface1 {
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFwoABgAQBwARCAASCgACABMHABQHABUHABYBAAY8aW5pdD4BAAMoKVYBAARDb2Rl" +
+ "AQAPTGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3Vy" +
+ "Y2VGaWxlAQAPVHJhbnNmb3JtMi5qYXZhDAAIAAkBAA9qYXZhL2xhbmcvRXJyb3IBABVTaG91bGQg" +
+ "bm90IGJlIGNhbGxlZCEMAAgADQEAClRyYW5zZm9ybTIBABBqYXZhL2xhbmcvT2JqZWN0AQAGSWZh" +
+ "Y2UxACAABQAGAAEABwAAAAIAAAAIAAkAAQAKAAAAHQABAAEAAAAFKrcAAbEAAAABAAsAAAAGAAEA" +
+ "AAABAAEADAANAAEACgAAACIAAwACAAAACrsAAlkSA7cABL8AAAABAAsAAAAGAAEAAAADAAEADgAA" +
+ "AAIADw==");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQDiWVay8/Z0/tXQaTTI+QtwTM65gRJVMOusAgAAcAAAAHhWNBIAAAAAAAAAABgCAAAM" +
+ "AAAAcAAAAAYAAACgAAAAAgAAALgAAAAAAAAAAAAAAAQAAADQAAAAAQAAAPAAAACcAQAAEAEAAFoB" +
+ "AABiAQAAbAEAAHoBAACNAQAAoQEAALUBAADMAQAA3QEAAOABAADkAQAA+AEAAAEAAAACAAAAAwAA" +
+ "AAQAAAAFAAAACAAAAAgAAAAFAAAAAAAAAAkAAAAFAAAAVAEAAAEAAAAAAAAAAQABAAsAAAACAAEA" +
+ "AAAAAAMAAAAAAAAAAQAAAAAAAAADAAAATAEAAAcAAAAAAAAACgIAAAAAAAABAAEAAQAAAP8BAAAE" +
+ "AAAAcBADAAAADgAEAAIAAgAAAAQCAAAJAAAAIgACABsBBgAAAHAgAgAQACcAAAABAAAAAAAAAAEA" +
+ "AAAEAAY8aW5pdD4ACExJZmFjZTE7AAxMVHJhbnNmb3JtMjsAEUxqYXZhL2xhbmcvRXJyb3I7ABJM" +
+ "amF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAVU2hvdWxkIG5vdCBiZSBjYWxs" +
+ "ZWQhAA9UcmFuc2Zvcm0yLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTQuMjAABXNheUhpAAEA" +
+ "Bw4AAwEABw4AAAABAQCAgASQAgEBqAIMAAAAAAAAAAEAAAAAAAAAAQAAAAwAAABwAAAAAgAAAAYA" +
+ "AACgAAAAAwAAAAIAAAC4AAAABQAAAAQAAADQAAAABgAAAAEAAADwAAAAASAAAAIAAAAQAQAAARAA" +
+ "AAIAAABMAQAAAiAAAAwAAABaAQAAAyAAAAIAAAD/AQAAACAAAAEAAAAKAgAAABAAAAEAAAAYAgAA");
+
+ public static void doTest(Transform2 t) {
+ t.sayHi("MissingInterface");
+ try {
+ Main.doCommonClassRedefinition(Transform2.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("MissingInterface");
+ }
+}
diff --git a/test/921-hello-failure/src/NewInterface.java b/test/921-hello-failure/src/NewInterface.java
new file mode 100644
index 0000000000..fe7722261a
--- /dev/null
+++ b/test/921-hello-failure/src/NewInterface.java
@@ -0,0 +1,59 @@
+/*
+ * 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 NewInterface {
+ // The following is a base64 encoding of the following class.
+ // class Transform2 implements Iface1, Iface2, Iface3 {
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAGwoABgASBwATCAAUCgACABUHABYHABcHABgHABkHABoBAAY8aW5pdD4BAAMoKVYB" +
+ "AARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYB" +
+ "AApTb3VyY2VGaWxlAQAPVHJhbnNmb3JtMi5qYXZhDAAKAAsBAA9qYXZhL2xhbmcvRXJyb3IBABVT" +
+ "aG91bGQgbm90IGJlIGNhbGxlZCEMAAoADwEAClRyYW5zZm9ybTIBABBqYXZhL2xhbmcvT2JqZWN0" +
+ "AQAGSWZhY2UxAQAGSWZhY2UyAQAGSWZhY2UzACAABQAGAAMABwAIAAkAAAACAAAACgALAAEADAAA" +
+ "AB0AAQABAAAABSq3AAGxAAAAAQANAAAABgABAAAAAQABAA4ADwABAAwAAAAiAAMAAgAAAAq7AAJZ" +
+ "EgO3AAS/AAAAAQANAAAABgABAAAAAwABABAAAAACABE=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQCBWnko4SMXeuXSO3fGJBp0WSlc0HLRr63UAgAAcAAAAHhWNBIAAAAAAAAAAEACAAAO" +
+ "AAAAcAAAAAgAAACoAAAAAgAAAMgAAAAAAAAAAAAAAAQAAADgAAAAAQAAAAABAAC0AQAAIAEAAG4B" +
+ "AAB2AQAAgAEAAIoBAACUAQAAogEAALUBAADJAQAA3QEAAPQBAAAFAgAACAIAAAwCAAAgAgAAAQAA" +
+ "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAoAAAAKAAAABwAAAAAAAAALAAAABwAAAGgBAAADAAAA" +
+ "AAAAAAMAAQANAAAABAABAAAAAAAFAAAAAAAAAAMAAAAAAAAABQAAAFwBAAAJAAAAAAAAADICAAAA" +
+ "AAAAAQABAAEAAAAnAgAABAAAAHAQAwAAAA4ABAACAAIAAAAsAgAACQAAACIABAAbAQgAAABwIAIA" +
+ "EAAnAAAAAwAAAAAAAQACAAAAAQAAAAYABjxpbml0PgAITElmYWNlMTsACExJZmFjZTI7AAhMSWZh" +
+ "Y2UzOwAMTFRyYW5zZm9ybTI7ABFMamF2YS9sYW5nL0Vycm9yOwASTGphdmEvbGFuZy9PYmplY3Q7" +
+ "ABJMamF2YS9sYW5nL1N0cmluZzsAFVNob3VsZCBub3QgYmUgY2FsbGVkIQAPVHJhbnNmb3JtMi5q" +
+ "YXZhAAFWAAJWTAASZW1pdHRlcjogamFjay00LjIwAAVzYXlIaQABAAcOAAMBAAcOAAAAAQEAgIAE" +
+ "oAIBAbgCDAAAAAAAAAABAAAAAAAAAAEAAAAOAAAAcAAAAAIAAAAIAAAAqAAAAAMAAAACAAAAyAAA" +
+ "AAUAAAAEAAAA4AAAAAYAAAABAAAAAAEAAAEgAAACAAAAIAEAAAEQAAACAAAAXAEAAAIgAAAOAAAA" +
+ "bgEAAAMgAAACAAAAJwIAAAAgAAABAAAAMgIAAAAQAAABAAAAQAIAAA==");
+
+ public static void doTest(Transform2 t) {
+ t.sayHi("NewInterface");
+ try {
+ Main.doCommonClassRedefinition(Transform2.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("NewInterface");
+ }
+}
diff --git a/test/921-hello-failure/src/NewName.java b/test/921-hello-failure/src/NewName.java
new file mode 100644
index 0000000000..a6f249a2ef
--- /dev/null
+++ b/test/921-hello-failure/src/NewName.java
@@ -0,0 +1,56 @@
+/*
+ * 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 NewName {
+ // class NotTransform {
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAFQoABgAPBwAQCAARCgACABIHABMHABQBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP" +
+ "TGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3VyY2VG" +
+ "aWxlAQARTm90VHJhbnNmb3JtLmphdmEMAAcACAEAD2phdmEvbGFuZy9FcnJvcgEAFVNob3VsZCBu" +
+ "b3QgYmUgY2FsbGVkIQwABwAMAQAMTm90VHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAAgAAUA" +
+ "BgAAAAAAAgAAAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAEAAQALAAwA" +
+ "AQAJAAAAIgADAAIAAAAKuwACWRIDtwAEvwAAAAEACgAAAAYAAQAAAAMAAQANAAAAAgAO");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQDLV95i5xnv6iUi6uIeDoY5jP5Xe9NP1AiYAgAAcAAAAHhWNBIAAAAAAAAAAAQCAAAL" +
+ "AAAAcAAAAAUAAACcAAAAAgAAALAAAAAAAAAAAAAAAAQAAADIAAAAAQAAAOgAAACQAQAACAEAAEoB" +
+ "AABSAQAAYgEAAHUBAACJAQAAnQEAALABAADHAQAAygEAAM4BAADiAQAAAQAAAAIAAAADAAAABAAA" +
+ "AAcAAAAHAAAABAAAAAAAAAAIAAAABAAAAEQBAAAAAAAAAAAAAAAAAQAKAAAAAQABAAAAAAACAAAA" +
+ "AAAAAAAAAAAAAAAAAgAAAAAAAAAFAAAAAAAAAPQBAAAAAAAAAQABAAEAAADpAQAABAAAAHAQAwAA" +
+ "AA4ABAACAAIAAADuAQAACQAAACIAAQAbAQYAAABwIAIAEAAnAAAAAQAAAAMABjxpbml0PgAOTE5v" +
+ "dFRyYW5zZm9ybTsAEUxqYXZhL2xhbmcvRXJyb3I7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZh" +
+ "L2xhbmcvU3RyaW5nOwARTm90VHJhbnNmb3JtLmphdmEAFVNob3VsZCBub3QgYmUgY2FsbGVkIQAB" +
+ "VgACVkwAEmVtaXR0ZXI6IGphY2stNC4yMAAFc2F5SGkAAQAHDgADAQAHDgAAAAEBAICABIgCAQGg" +
+ "AgAADAAAAAAAAAABAAAAAAAAAAEAAAALAAAAcAAAAAIAAAAFAAAAnAAAAAMAAAACAAAAsAAAAAUA" +
+ "AAAEAAAAyAAAAAYAAAABAAAA6AAAAAEgAAACAAAACAEAAAEQAAABAAAARAEAAAIgAAALAAAASgEA" +
+ "AAMgAAACAAAA6QEAAAAgAAABAAAA9AEAAAAQAAABAAAABAIAAA==");
+
+ public static void doTest(Transform t) {
+ t.sayHi("NewName");
+ try {
+ Main.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("NewName");
+ }
+}
diff --git a/test/921-hello-failure/src/ReorderInterface.java b/test/921-hello-failure/src/ReorderInterface.java
new file mode 100644
index 0000000000..ce78dbc241
--- /dev/null
+++ b/test/921-hello-failure/src/ReorderInterface.java
@@ -0,0 +1,59 @@
+/*
+ * 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 ReorderInterface {
+ // The following is a base64 encoding of the following class.
+ // class Transform2 implements Iface2, Iface1 {
+ // public void sayHi(String name) {
+ // throw new Error("Should not be called!");
+ // }
+ // }
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADQAGQoABgARBwASCAATCgACABQHABUHABYHABcHABgBAAY8aW5pdD4BAAMoKVYBAARD" +
+ "b2RlAQAPTGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApT" +
+ "b3VyY2VGaWxlAQAPVHJhbnNmb3JtMi5qYXZhDAAJAAoBAA9qYXZhL2xhbmcvRXJyb3IBABVTaG91" +
+ "bGQgbm90IGJlIGNhbGxlZCEMAAkADgEAClRyYW5zZm9ybTIBABBqYXZhL2xhbmcvT2JqZWN0AQAG" +
+ "SWZhY2UyAQAGSWZhY2UxACAABQAGAAIABwAIAAAAAgAAAAkACgABAAsAAAAdAAEAAQAAAAUqtwAB" +
+ "sQAAAAEADAAAAAYAAQAAAAEAAQANAA4AAQALAAAAIgADAAIAAAAKuwACWRIDtwAEvwAAAAEADAAA" +
+ "AAYAAQAAAAMAAQAPAAAAAgAQ");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQChWfUC02YEHJZLC4V4pHrGMdqwD8NnzXvAAgAAcAAAAHhWNBIAAAAAAAAAACwCAAAN" +
+ "AAAAcAAAAAcAAACkAAAAAgAAAMAAAAAAAAAAAAAAAAQAAADYAAAAAQAAAPgAAACoAQAAGAEAAGIB" +
+ "AABqAQAAdAEAAH4BAACMAQAAnwEAALMBAADHAQAA3gEAAO8BAADyAQAA9gEAAAoCAAABAAAAAgAA" +
+ "AAMAAAAEAAAABQAAAAYAAAAJAAAACQAAAAYAAAAAAAAACgAAAAYAAABcAQAAAgAAAAAAAAACAAEA" +
+ "DAAAAAMAAQAAAAAABAAAAAAAAAACAAAAAAAAAAQAAABUAQAACAAAAAAAAAAcAgAAAAAAAAEAAQAB" +
+ "AAAAEQIAAAQAAABwEAMAAAAOAAQAAgACAAAAFgIAAAkAAAAiAAMAGwEHAAAAcCACABAAJwAAAAIA" +
+ "AAABAAAAAQAAAAUABjxpbml0PgAITElmYWNlMTsACExJZmFjZTI7AAxMVHJhbnNmb3JtMjsAEUxq" +
+ "YXZhL2xhbmcvRXJyb3I7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAV" +
+ "U2hvdWxkIG5vdCBiZSBjYWxsZWQhAA9UcmFuc2Zvcm0yLmphdmEAAVYAAlZMABJlbWl0dGVyOiBq" +
+ "YWNrLTQuMjAABXNheUhpAAEABw4AAwEABw4AAAABAQCAgASYAgEBsAIAAAwAAAAAAAAAAQAAAAAA" +
+ "AAABAAAADQAAAHAAAAACAAAABwAAAKQAAAADAAAAAgAAAMAAAAAFAAAABAAAANgAAAAGAAAAAQAA" +
+ "APgAAAABIAAAAgAAABgBAAABEAAAAgAAAFQBAAACIAAADQAAAGIBAAADIAAAAgAAABECAAAAIAAA" +
+ "AQAAABwCAAAAEAAAAQAAACwCAAA=");
+
+ public static void doTest(Transform2 t) {
+ t.sayHi("ReorderInterface");
+ try {
+ Main.doCommonClassRedefinition(Transform2.class, CLASS_BYTES, DEX_BYTES);
+ } catch (Exception e) {
+ System.out.println(
+ "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")");
+ }
+ t.sayHi("ReorderInterface");
+ }
+}
diff --git a/test/921-hello-failure/src/Transform.java b/test/921-hello-failure/src/Transform.java
new file mode 100644
index 0000000000..ee444f0606
--- /dev/null
+++ b/test/921-hello-failure/src/Transform.java
@@ -0,0 +1,21 @@
+/*
+ * 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 Transform {
+ public void sayHi(String name) {
+ System.out.println("hello - " + name);
+ }
+}
diff --git a/test/921-hello-failure/src/Transform2.java b/test/921-hello-failure/src/Transform2.java
new file mode 100644
index 0000000000..9d949f323f
--- /dev/null
+++ b/test/921-hello-failure/src/Transform2.java
@@ -0,0 +1,21 @@
+/*
+ * 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 Transform2 implements Iface1, Iface2 {
+ public void sayHi(String name) {
+ System.out.println("hello2 - " + name);
+ }
+}
diff --git a/test/922-properties/build b/test/922-properties/build
new file mode 100755
index 0000000000..898e2e54a2
--- /dev/null
+++ b/test/922-properties/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/922-properties/expected.txt b/test/922-properties/expected.txt
new file mode 100644
index 0000000000..0be939be3d
--- /dev/null
+++ b/test/922-properties/expected.txt
@@ -0,0 +1,59 @@
+Recommended properties:
+ "java.class.path": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.library.path": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.info": OK !!!JVMTI_ERROR_NOT_AVAILABLE
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.name": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.vendor": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.version": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+Missing recommended properties: [java.vm.info]
+Other properties:
+ "file.encoding": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "file.separator": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.class.version": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.compiler": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.ext.dirs": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.net.preferIPv6Addresses": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.specification.name": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.specification.vendor": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.specification.version": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vendor": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vendor.url": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.version": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.specification.name": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.specification.vendor": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.specification.version": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "java.vm.vendor.url": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "line.separator": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "os.name": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+ "path.separator": OK
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+Non-specified property:
+ "java.boot.class.path": ERROR !!!JVMTI_ERROR_NOT_AVAILABLE
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
+Non-specified property (2):
+ "a": OK !!!JVMTI_ERROR_NOT_AVAILABLE
+ Setting value to "abc": !!!JVMTI_ERROR_NOT_AVAILABLE
diff --git a/test/922-properties/info.txt b/test/922-properties/info.txt
new file mode 100644
index 0000000000..875a5f6ec1
--- /dev/null
+++ b/test/922-properties/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/922-properties/properties.cc b/test/922-properties/properties.cc
new file mode 100644
index 0000000000..b1e7fce3b5
--- /dev/null
+++ b/test/922-properties/properties.cc
@@ -0,0 +1,107 @@
+/*
+ * 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 "properties.h"
+
+#include <stdio.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 Test922Properties {
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getSystemProperties(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) {
+ jint count;
+ char** properties;
+ jvmtiError result = jvmti_env->GetSystemProperties(&count, &properties);
+ if (JvmtiErrorToException(env, result)) {
+ return nullptr;
+ }
+
+ auto callback = [&](jint i) -> jstring {
+ char* data = properties[i];
+ if (data == nullptr) {
+ return nullptr;
+ }
+ jstring ret = env->NewStringUTF(data);
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(data));
+ return ret;
+ };
+ jobjectArray ret = CreateObjectArray(env, count, "java/lang/String", callback);
+
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(properties));
+
+ return ret;
+}
+
+extern "C" JNIEXPORT jstring JNICALL Java_Main_getSystemProperty(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jstring key) {
+ ScopedUtfChars string(env, key);
+ if (string.c_str() == nullptr) {
+ return nullptr;
+ }
+
+ char* value = nullptr;
+ jvmtiError result = jvmti_env->GetSystemProperty(string.c_str(), &value);
+ if (JvmtiErrorToException(env, result)) {
+ return nullptr;
+ }
+
+ jstring ret = (value == nullptr) ? nullptr : env->NewStringUTF(value);
+
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(value));
+
+ return ret;
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_setSystemProperty(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jstring key, jstring value) {
+ ScopedUtfChars key_string(env, key);
+ if (key_string.c_str() == nullptr) {
+ return;
+ }
+ ScopedUtfChars value_string(env, value);
+ if (value_string.c_str() == nullptr) {
+ return;
+ }
+
+ jvmtiError result = jvmti_env->SetSystemProperty(key_string.c_str(), value_string.c_str());
+ if (JvmtiErrorToException(env, result)) {
+ return;
+ }
+}
+
+// Don't do anything
+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);
+ return 0;
+}
+
+} // namespace Test922Properties
+} // namespace art
diff --git a/test/922-properties/properties.h b/test/922-properties/properties.h
new file mode 100644
index 0000000000..84feb10758
--- /dev/null
+++ b/test/922-properties/properties.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_TEST_922_PROPERTIES_PROPERTIES_H_
+#define ART_TEST_922_PROPERTIES_PROPERTIES_H_
+
+#include <jni.h>
+
+namespace art {
+namespace Test922Properties {
+
+jint OnLoad(JavaVM* vm, char* options, void* reserved);
+
+} // namespace Test922Properties
+} // namespace art
+
+#endif // ART_TEST_922_PROPERTIES_PROPERTIES_H_
diff --git a/test/922-properties/run b/test/922-properties/run
new file mode 100755
index 0000000000..4379349cb2
--- /dev/null
+++ b/test/922-properties/run
@@ -0,0 +1,19 @@
+#!/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 "$@" --experimental agents \
+ --experimental runtime-plugins \
+ --jvmti
diff --git a/test/922-properties/src/Main.java b/test/922-properties/src/Main.java
new file mode 100644
index 0000000000..6cec6e97f2
--- /dev/null
+++ b/test/922-properties/src/Main.java
@@ -0,0 +1,155 @@
+/*
+ * 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.Set;
+import java.util.TreeSet;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[1]);
+
+ doTest();
+ }
+
+ public static void doTest() throws Exception {
+ Set<String> recommendedProperties = getRecommendedProperties();
+
+ System.out.println("Recommended properties:");
+ for (String key : recommendedProperties) {
+ checkProperty(key);
+ }
+
+ Set<String> allProperties = getAllProperties();
+
+ Set<String> retained = new TreeSet<String>(recommendedProperties);
+ retained.retainAll(allProperties);
+ if (!retained.equals(recommendedProperties)) {
+ Set<String> missing = new TreeSet<String>(recommendedProperties);
+ missing.removeAll(retained);
+ System.out.println("Missing recommended properties: " + missing);
+ }
+
+ Set<String> nonRecommended = new TreeSet<String>(allProperties);
+ nonRecommended.removeAll(recommendedProperties);
+
+ System.out.println("Other properties:");
+ for (String key : nonRecommended) {
+ checkProperty(key);
+ }
+
+ System.out.println("Non-specified property:");
+ String key = generate(allProperties);
+ checkProperty(key);
+
+ System.out.println("Non-specified property (2):");
+ String key2 = generateUnique(allProperties);
+ checkProperty(key2);
+ }
+
+ private static Set<String> getRecommendedProperties() {
+ Set<String> keys = new TreeSet<String>();
+ keys.add("java.vm.vendor");
+ keys.add("java.vm.version");
+ keys.add("java.vm.name");
+ keys.add("java.vm.info");
+ keys.add("java.library.path");
+ keys.add("java.class.path");
+ return keys;
+ }
+
+ private static Set<String> getAllProperties() {
+ Set<String> keys = new TreeSet<String>();
+ String[] props = getSystemProperties();
+ for (String p : props) {
+ keys.add(p);
+ }
+ return keys;
+ }
+
+ private static boolean equals(String s1, String s2) {
+ if (s1 == null && s2 == null) {
+ return true;
+ } else if (s1 != null) {
+ return s1.equals(s2);
+ } else {
+ return false;
+ }
+ }
+
+ private static void checkProperty(String key) {
+ System.out.print(" \"" + key + "\": ");
+ String err = null;
+ String value = null;
+ try {
+ value = getSystemProperty(key);
+ } catch (RuntimeException e) {
+ err = e.getMessage();
+ }
+ String sysValue = System.getProperty(key);
+ if (equals(value, sysValue)) {
+ System.out.print("OK");
+ if (err != null) {
+ System.out.println(" !!!" + err);
+ } else {
+ System.out.println();
+ }
+ } else {
+ System.out.println("ERROR !!!" + err);
+ }
+
+ System.out.print(" Setting value to \"abc\": ");
+ try {
+ setSystemProperty(key, "abc");
+ System.out.println("SUCCEEDED");
+ } catch (RuntimeException e) {
+ System.out.println("!!!" + e.getMessage());
+ }
+ }
+
+ private static String generateUnique(Set<String> others) {
+ // Construct something. To be deterministic, just use "a+".
+ StringBuilder sb = new StringBuilder("a");
+ for (;;) {
+ String key = sb.toString();
+ if (!others.contains(key)) {
+ return key;
+ }
+ sb.append('a');
+ }
+ }
+
+ private static String generate(Set<String> others) {
+ // First check for something in the overall System properties.
+ TreeSet<String> sysProps = new TreeSet<String>(System.getProperties().stringPropertyNames());
+ sysProps.removeAll(others);
+ if (!sysProps.isEmpty()) {
+ // Find something that starts with "java" or "os," trying to be platform-independent.
+ for (String s: sysProps) {
+ if (s.startsWith("java.") || s.startsWith("os.")) {
+ return s;
+ }
+ }
+ // Just return the first thing.
+ return sysProps.iterator().next();
+ }
+
+ return generateUnique(others);
+ }
+
+ private static native String[] getSystemProperties();
+ private static native String getSystemProperty(String key);
+ private static native void setSystemProperty(String key, String value);
+}
diff --git a/test/Android.bp b/test/Android.bp
index 5a2c90230e..f6648d1cdc 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -260,6 +260,9 @@ art_cc_defaults {
"911-get-stack-trace/stack_trace.cc",
"912-classes/classes.cc",
"913-heaps/heaps.cc",
+ "918-fields/fields.cc",
+ "920-objects/objects.cc",
+ "922-properties/properties.cc",
],
shared_libs: [
"libbase",
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index ec1f6ba239..a3f6864883 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -290,6 +290,11 @@ TEST_ART_BROKEN_TARGET_TESTS += \
915-obsolete-2 \
916-obsolete-jit \
917-fields-transformation \
+ 918-fields \
+ 919-obsolete-fields \
+ 920-objects \
+ 921-hello-failure \
+ 922-properties \
ifneq (,$(filter target,$(TARGET_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES), \
@@ -543,7 +548,7 @@ TEST_ART_BROKEN_INTERPRETER_RUN_TESTS :=
# between those runs to be able to have precise checks.
# Test 902 hits races with the JIT compiler. b/32821077
# Test 629 requires compilation.
-# Test 914, 915, 917, & 918 are very sensitive to the exact state of the stack,
+# Test 914, 915, 917, & 919 are very sensitive to the exact state of the stack,
# including the jit-inserted runtime frames. This causes them to be somewhat
# flaky as JIT tests. This should be fixed once b/33630159 or b/33616143 are
# resolved but until then just disable them. Test 916 already checks this
@@ -557,7 +562,7 @@ TEST_ART_BROKEN_JIT_RUN_TESTS := \
914-hello-obsolescence \
915-obsolete-2 \
917-fields-transformation \
- 918-obsolete-fields \
+ 919-obsolete-fields \
ifneq (,$(filter jit,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
@@ -1021,10 +1026,11 @@ define define-test-art-run-test
test_groups += ART_RUN_TEST_$$(uc_host_or_target)_NO_IMAGE_RULES
run_test_options += --no-image
# Add the core dependency. This is required for pre-building.
+ # Use the PIC image, as it is the default in run-test, to match dependencies.
ifeq ($(1),host)
- prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_no-pic_$(13))
+ prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_pic_$(13))
else
- prereq_rule += $$(TARGET_CORE_IMAGE_$$(image_suffix)_no-pic_$(13))
+ prereq_rule += $$(TARGET_CORE_IMAGE_$$(image_suffix)_pic_$(13))
endif
else
ifeq ($(9),npicimage)
diff --git a/test/ti-agent/common_helper.cc b/test/ti-agent/common_helper.cc
index ebf1e4621c..6f98f10072 100644
--- a/test/ti-agent/common_helper.cc
+++ b/test/ti-agent/common_helper.cc
@@ -17,6 +17,7 @@
#include "ti-agent/common_helper.h"
#include <stdio.h>
+#include <sstream>
#include "art_method.h"
#include "jni.h"
@@ -39,10 +40,46 @@ void SetAllCapabilities(jvmtiEnv* env) {
env->AddCapabilities(&caps);
}
+bool JvmtiErrorToException(JNIEnv* env, jvmtiError error) {
+ if (error == JVMTI_ERROR_NONE) {
+ return false;
+ }
+
+ ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException"));
+ if (rt_exception.get() == nullptr) {
+ // CNFE should be pending.
+ return true;
+ }
+
+ char* err;
+ jvmti_env->GetErrorName(error, &err);
+
+ env->ThrowNew(rt_exception.get(), err);
+
+ jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err));
+ return true;
+}
+
namespace common_redefine {
+static void throwRedefinitionError(jvmtiEnv* jvmti, JNIEnv* env, jclass target, jvmtiError res) {
+ std::stringstream err;
+ char* signature = nullptr;
+ char* generic = nullptr;
+ jvmti->GetClassSignature(target, &signature, &generic);
+ char* error = nullptr;
+ jvmti->GetErrorName(res, &error);
+ err << "Failed to redefine class <" << signature << "> due to " << error;
+ std::string message = err.str();
+ jvmti->Deallocate(reinterpret_cast<unsigned char*>(signature));
+ jvmti->Deallocate(reinterpret_cast<unsigned char*>(generic));
+ jvmti->Deallocate(reinterpret_cast<unsigned char*>(error));
+ env->ThrowNew(env->FindClass("java/lang/Exception"), message.c_str());
+}
+
using RedefineDirectFunction = jvmtiError (*)(jvmtiEnv*, jclass, jint, const unsigned char*);
-static void DoClassTransformation(jvmtiEnv* jvmti_env, JNIEnv* env,
+static void DoClassTransformation(jvmtiEnv* jvmti_env,
+ JNIEnv* env,
jclass target,
jbyteArray class_file_bytes,
jbyteArray dex_file_bytes) {
@@ -63,7 +100,7 @@ static void DoClassTransformation(jvmtiEnv* jvmti_env, JNIEnv* env,
res = f(jvmti_env, target, len, redef_bytes);
}
if (res != JVMTI_ERROR_NONE) {
- printf("Redefinition failed!");
+ throwRedefinitionError(jvmti_env, env, target, res);
}
}
diff --git a/test/ti-agent/common_helper.h b/test/ti-agent/common_helper.h
index 76543fed23..642ca03274 100644
--- a/test/ti-agent/common_helper.h
+++ b/test/ti-agent/common_helper.h
@@ -65,6 +65,8 @@ static jobjectArray CreateObjectArray(JNIEnv* env,
void SetAllCapabilities(jvmtiEnv* env);
+bool JvmtiErrorToException(JNIEnv* env, jvmtiError error);
+
} // namespace art
#endif // ART_TEST_TI_AGENT_COMMON_HELPER_H_
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 79c17d744f..e309a8920b 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -37,6 +37,9 @@
#include "911-get-stack-trace/stack_trace.h"
#include "912-classes/classes.h"
#include "913-heaps/heaps.h"
+#include "918-fields/fields.h"
+#include "920-objects/objects.h"
+#include "922-properties/properties.h"
namespace art {
@@ -70,6 +73,11 @@ AgentLib agents[] = {
{ "915-obsolete-2", common_redefine::OnLoad, nullptr },
{ "916-obsolete-jit", common_redefine::OnLoad, nullptr },
{ "917-fields-transformation", common_redefine::OnLoad, nullptr },
+ { "918-fields", Test918Fields::OnLoad, nullptr },
+ { "919-obsolete-fields", common_redefine::OnLoad, nullptr },
+ { "920-objects", Test920Objects::OnLoad, nullptr },
+ { "921-hello-failure", common_redefine::OnLoad, nullptr },
+ { "922-properties", Test922Properties::OnLoad, nullptr },
};
static AgentLib* FindAgent(char* name) {
diff --git a/test/valgrind-target-suppressions.txt b/test/valgrind-target-suppressions.txt
index fbc99b12ce..452a17412a 100644
--- a/test/valgrind-target-suppressions.txt
+++ b/test/valgrind-target-suppressions.txt
@@ -36,8 +36,7 @@
MemCpySelfAssign
Memcheck:Overlap
fun:memcpy
- fun:je_tsd_set
- fun:je_tsd_fetch
+ ...
fun:je_malloc_tsd_boot0
}
@@ -59,3 +58,12 @@
...
fun:_ZN3art7Runtime17InitNativeMethodsEv
}
+
+# art::MemMap::MapInternal() uses msync() to check for the existence of memory mappings.
+{
+ art::MemMap::MapInternal()
+ Memcheck:Param
+ msync(start)
+ fun:msync
+ fun:_ZN3art6MemMap11MapInternalEPvmiiilb
+}