diff options
author | Jeff Hao <jeffhao@google.com> | 2015-05-19 20:30:23 -0700 |
---|---|---|
committer | Jeff Hao <jeffhao@google.com> | 2015-05-20 18:32:14 -0700 |
commit | 15e9ad1d028d7f12cb598b075453173532a00d91 (patch) | |
tree | f31edd7f7e10d8372c452229b4f9eb749647864f /test | |
parent | 5d52f3dca52548f4a4598abd06432cad3dca6b8a (diff) | |
download | android_art-15e9ad1d028d7f12cb598b075453173532a00d91.tar.gz android_art-15e9ad1d028d7f12cb598b075453173532a00d91.tar.bz2 android_art-15e9ad1d028d7f12cb598b075453173532a00d91.zip |
Intercept JNI invocation of String.<init> methods.
libmono uses JNI AllocObject and CallNonvirtualVoidMethod to create and
initialize a string instead of using the recommended NewObject. This
change adds an intercept to change the String.<init> call to a
StringFactory call instead. Then, it uses the object id of the original
string object referrer and maps it to the result of the StringFactory.
Bug: 21288130
Change-Id: Ib4db402c178bc37188d5c5faf30b6e4fdc747b17
Diffstat (limited to 'test')
-rw-r--r-- | test/004-JniTest/jni_test.cc | 63 | ||||
-rw-r--r-- | test/020-string/src/Main.java | 36 |
2 files changed, 86 insertions, 13 deletions
diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc index cdc546155d..1ec0cf2d43 100644 --- a/test/004-JniTest/jni_test.cc +++ b/test/004-JniTest/jni_test.cc @@ -550,21 +550,58 @@ extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) { } extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) { - const char* string = "Test"; - int length = strlen(string); jclass c = env->FindClass("java/lang/String"); - assert(c != NULL); - jmethodID method = env->GetMethodID(c, "<init>", "([B)V"); - assert(method != NULL); + assert(c != nullptr); + + jmethodID mid1 = env->GetMethodID(c, "<init>", "()V"); + assert(mid1 != nullptr); + assert(!env->ExceptionCheck()); + jmethodID mid2 = env->GetMethodID(c, "<init>", "([B)V"); + assert(mid2 != nullptr); + assert(!env->ExceptionCheck()); + jmethodID mid3 = env->GetMethodID(c, "<init>", "([C)V"); + assert(mid3 != nullptr); + assert(!env->ExceptionCheck()); + jmethodID mid4 = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V"); + assert(mid4 != nullptr); assert(!env->ExceptionCheck()); - jbyteArray array = env->NewByteArray(length); - env->SetByteArrayRegion(array, 0, length, reinterpret_cast<const jbyte*>(string)); - jobject o = env->NewObject(c, method, array); - assert(o != NULL); - jstring s = reinterpret_cast<jstring>(o); - assert(env->GetStringLength(s) == length); - assert(env->GetStringUTFLength(s) == length); + + const char* test_array = "Test"; + int byte_array_length = strlen(test_array); + jbyteArray byte_array = env->NewByteArray(byte_array_length); + env->SetByteArrayRegion(byte_array, 0, byte_array_length, reinterpret_cast<const jbyte*>(test_array)); + + // Test NewObject + jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array)); + assert(s != nullptr); + assert(env->GetStringLength(s) == byte_array_length); + assert(env->GetStringUTFLength(s) == byte_array_length); const char* chars = env->GetStringUTFChars(s, nullptr); - assert(strcmp(string, chars) == 0); + assert(strcmp(test_array, chars) == 0); env->ReleaseStringUTFChars(s, chars); + + // Test AllocObject and Call(Nonvirtual)VoidMethod + jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s1 != nullptr); + jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s2 != nullptr); + jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s3 != nullptr); + jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c)); + assert(s4 != nullptr); + + jcharArray char_array = env->NewCharArray(5); + jstring string_arg = env->NewStringUTF("helloworld"); + + // With Var Args + env->CallVoidMethod(s1, mid1); + env->CallNonvirtualVoidMethod(s2, c, mid2, byte_array); + + // With JValues + jvalue args3[1]; + args3[0].l = char_array; + jvalue args4[1]; + args4[0].l = string_arg; + env->CallVoidMethodA(s3, mid3, args3); + env->CallNonvirtualVoidMethodA(s4, c, mid4, args4); } diff --git a/test/020-string/src/Main.java b/test/020-string/src/Main.java index bb8ce1fa51..b876e6ad21 100644 --- a/test/020-string/src/Main.java +++ b/test/020-string/src/Main.java @@ -14,6 +14,9 @@ * limitations under the License. */ +import java.nio.charset.Charset; +import java.io.UnsupportedEncodingException; + /** * Simple string test. */ @@ -21,6 +24,7 @@ public class Main { public static void main(String args[]) { basicTest(); indexTest(); + constructorTest(); } public static void basicTest() { @@ -81,4 +85,36 @@ public class Main { subStr.indexOf('&') + ":" + baseStr.indexOf(0x12341234)); } + + public static void constructorTest() { + byte[] byteArray = "byteArray".getBytes(); + char[] charArray = new char[] { 'c', 'h', 'a', 'r', 'A', 'r', 'r', 'a', 'y' }; + String charsetName = "US-ASCII"; + Charset charset = Charset.forName("UTF-8"); + String string = "string"; + StringBuffer stringBuffer = new StringBuffer("stringBuffer"); + int [] codePoints = new int[] { 65, 66, 67, 68, 69 }; + StringBuilder stringBuilder = new StringBuilder("stringBuilder"); + + String s1 = new String(); + String s2 = new String(byteArray); + String s3 = new String(byteArray, 1); + String s4 = new String(byteArray, 0, 4); + String s5 = new String(byteArray, 2, 4, 5); + + try { + String s6 = new String(byteArray, 2, 4, charsetName); + String s7 = new String(byteArray, charsetName); + } catch (UnsupportedEncodingException e) { + System.out.println("Got unexpected UnsupportedEncodingException"); + } + String s8 = new String(byteArray, 3, 3, charset); + String s9 = new String(byteArray, charset); + String s10 = new String(charArray); + String s11 = new String(charArray, 0, 4); + String s12 = new String(string); + String s13 = new String(stringBuffer); + String s14 = new String(codePoints, 1, 3); + String s15 = new String(stringBuilder); + } } |