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,
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
char** name_ptr,
char** signature_ptr,
char** generic_ptr);
+
+ static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env,
+ jmethodID method,
+ jclass* declaring_class_ptr);
};
} // namespace openjdkjvmti
[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
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,
*/
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.util.Arrays;
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);
}