OSDN Git Service

ART: Add GetMethodDeclaringClass
authorAndreas Gampe <agampe@google.com>
Sat, 29 Oct 2016 00:33:13 +0000 (17:33 -0700)
committerAndreas Gampe <agampe@google.com>
Sat, 29 Oct 2016 00:33:13 +0000 (17:33 -0700)
Support GetMethodDeclaringClass to retrieve the declaring class
of a JNI method.

Extend test 910. Also cover proxies.

Bug: 31684812
Test: m test-art-host-run-test-910-methods
Change-Id: I8508f96f88692e540ef53f693ff85590b7553f19

runtime/openjdkjvmti/OpenjdkJvmTi.cc
runtime/openjdkjvmti/ti_method.cc
runtime/openjdkjvmti/ti_method.h
test/910-methods/expected.txt
test/910-methods/methods.cc
test/910-methods/src/Main.java

index 10e877a..f95ec59 100644 (file)
@@ -648,7 +648,7 @@ class JvmtiFunctions {
   static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env,
                                             jmethodID method,
                                             jclass* declaring_class_ptr) {
-    return ERR(NOT_IMPLEMENTED);
+    return MethodUtil::GetMethodDeclaringClass(env, method, declaring_class_ptr);
   }
 
   static jvmtiError GetMethodModifiers(jvmtiEnv* env,
index 8d943d9..4aae4d1 100644 (file)
@@ -97,4 +97,21 @@ jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env,
   return ERR(NONE);
 }
 
+jvmtiError MethodUtil::GetMethodDeclaringClass(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                               jmethodID method,
+                                               jclass* declaring_class_ptr) {
+  if (declaring_class_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtMethod* art_method = soa.DecodeMethod(method);
+  // Note: No GetInterfaceMethodIfProxy, we want to actual class.
+
+  art::mirror::Class* klass = art_method->GetDeclaringClass();
+  *declaring_class_ptr = soa.AddLocalReference<jclass>(klass);
+
+  return ERR(NONE);
+}
+
 }  // namespace openjdkjvmti
index 17a3728..7cae0bf 100644 (file)
@@ -44,6 +44,10 @@ class MethodUtil {
                                   char** name_ptr,
                                   char** signature_ptr,
                                   char** generic_ptr);
+
+  static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env,
+                                            jmethodID method,
+                                            jclass* declaring_class_ptr);
 };
 
 }  // namespace openjdkjvmti
index b305d0f..980edc3 100644 (file)
@@ -1,4 +1,10 @@
 [toString, ()Ljava/lang/String;, null]
+class java.lang.Object
 [charAt, (I)C, null]
+class java.lang.String
 [sqrt, (D)D, null]
+class java.lang.Math
 [add, (Ljava/lang/Object;)Z, null]
+interface java.util.List
+[run, ()V, null]
+class $Proxy0
index fa910c1..214ae50 100644 (file)
@@ -75,6 +75,22 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getMethodName(
   return ret;
 }
 
+extern "C" JNIEXPORT jclass JNICALL Java_Main_getMethodDeclaringClass(
+    JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+  jmethodID id = env->FromReflectedMethod(method);
+
+  jclass declaring_class;
+  jvmtiError result = jvmti_env->GetMethodDeclaringClass(id, &declaring_class);
+  if (result != JVMTI_ERROR_NONE) {
+    char* err;
+    jvmti_env->GetErrorName(result, &err);
+    printf("Failure running GetMethodDeclaringClass: %s\n", err);
+    return nullptr;
+  }
+
+  return declaring_class;
+}
+
 // Don't do anything
 jint OnLoad(JavaVM* vm,
             char* options ATTRIBUTE_UNUSED,
index 1af30ba..d8c4627 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.Arrays;
 
 public class Main {
@@ -29,15 +30,40 @@ public class Main {
     testMethod("java.lang.String", "charAt", int.class);
     testMethod("java.lang.Math", "sqrt", double.class);
     testMethod("java.util.List", "add", Object.class);
+
+    testMethod(getProxyClass(), "run");
+  }
+
+  private static Class<?> proxyClass = null;
+
+  private static Class<?> getProxyClass() throws Exception {
+    if (proxyClass != null) {
+      return proxyClass;
+    }
+
+    proxyClass = Proxy.getProxyClass(Main.class.getClassLoader(), new Class[] { Runnable.class });
+    return proxyClass;
   }
 
   private static void testMethod(String className, String methodName, Class<?>... types)
       throws Exception {
     Class<?> base = Class.forName(className);
+    testMethod(base, methodName, types);
+  }
+
+  private static void testMethod(Class<?> base, String methodName, Class<?>... types)
+      throws Exception {
     Method m = base.getDeclaredMethod(methodName, types);
     String[] result = getMethodName(m);
     System.out.println(Arrays.toString(result));
+
+    Class<?> declClass = getMethodDeclaringClass(m);
+    if (base != declClass) {
+      throw new RuntimeException("Declaring class not equal: " + base + " vs " + declClass);
+    }
+    System.out.println(declClass);
   }
 
   private static native String[] getMethodName(Method m);
+  private static native Class<?> getMethodDeclaringClass(Method m);
 }