From: Andreas Gampe Date: Mon, 9 Jan 2017 22:40:25 +0000 (-0800) Subject: ART: Add method modifiers functions X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=fdeef52e2b7df4cd2184bb42deb8f1e4325cedce;p=android-x86%2Fart.git ART: Add method modifiers functions Add support for IsMethodNative, IsMethodObsolete and IsMethodSynthetic. Add tests. Bug: 34163329 Test: m test-art-host-run-test-910-methods Change-Id: I89077cfde1f37861ccb718345b753dfae1d6abe3 --- diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index c32f8b7dd..9569a91a2 100644 --- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc +++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc @@ -727,15 +727,15 @@ class JvmtiFunctions { } static jvmtiError IsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr) { - return ERR(NOT_IMPLEMENTED); + return MethodUtil::IsMethodNative(env, method, is_native_ptr); } static jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr) { - return ERR(NOT_IMPLEMENTED); + return MethodUtil::IsMethodSynthetic(env, method, is_synthetic_ptr); } static jvmtiError IsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr) { - return ERR(NOT_IMPLEMENTED); + return MethodUtil::IsMethodObsolete(env, method, is_obsolete_ptr); } static jvmtiError SetNativeMethodPrefix(jvmtiEnv* env, const char* prefix) { diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc index bb48a2b54..2ddd64a2b 100644 --- a/runtime/openjdkjvmti/ti_method.cc +++ b/runtime/openjdkjvmti/ti_method.cc @@ -280,4 +280,43 @@ jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env, return ERR(NONE); } +template +static jvmtiError IsMethodT(jvmtiEnv* env ATTRIBUTE_UNUSED, + jmethodID method, + T test, + jboolean* is_t_ptr) { + if (method == nullptr) { + return ERR(INVALID_METHODID); + } + if (is_t_ptr == nullptr) { + return ERR(NULL_POINTER); + } + + art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); + *is_t_ptr = test(art_method) ? JNI_TRUE : JNI_FALSE; + + return ERR(NONE); +} + +jvmtiError MethodUtil::IsMethodNative(jvmtiEnv* env, jmethodID m, jboolean* is_native_ptr) { + auto test = [](art::ArtMethod* method) { + return method->IsNative(); + }; + return IsMethodT(env, m, test, is_native_ptr); +} + +jvmtiError MethodUtil::IsMethodObsolete(jvmtiEnv* env, jmethodID m, jboolean* is_obsolete_ptr) { + auto test = [](art::ArtMethod* method) { + return method->IsObsolete(); + }; + return IsMethodT(env, m, test, is_obsolete_ptr); +} + +jvmtiError MethodUtil::IsMethodSynthetic(jvmtiEnv* env, jmethodID m, jboolean* is_synthetic_ptr) { + auto test = [](art::ArtMethod* method) { + return method->IsSynthetic(); + }; + return IsMethodT(env, m, test, is_synthetic_ptr); +} + } // namespace openjdkjvmti diff --git a/runtime/openjdkjvmti/ti_method.h b/runtime/openjdkjvmti/ti_method.h index ed606206a..e5c1705ad 100644 --- a/runtime/openjdkjvmti/ti_method.h +++ b/runtime/openjdkjvmti/ti_method.h @@ -66,6 +66,10 @@ class MethodUtil { jmethodID method, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr); + + static jvmtiError IsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr); + static jvmtiError IsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr); + static jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr); }; } // namespace openjdkjvmti diff --git a/test/910-methods/expected.txt b/test/910-methods/expected.txt index 539f85bcf..c913b3ffe 100644 --- a/test/910-methods/expected.txt +++ b/test/910-methods/expected.txt @@ -5,6 +5,9 @@ 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 @@ -12,6 +15,9 @@ 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 @@ -19,6 +25,9 @@ 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 @@ -26,6 +35,9 @@ 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 @@ -33,3 +45,15 @@ 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 d3e49871a..0f8892e50 100644 --- a/test/910-methods/methods.cc +++ b/test/910-methods/methods.cc @@ -188,6 +188,45 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_getMethodLocationEnd( 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 (ErrorToException(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 (ErrorToException(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 (ErrorToException(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 8f722e82e..bf25a0d02 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) { @@ -96,6 +109,29 @@ public class Main { } 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); @@ -105,4 +141,7 @@ public class Main { 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); }