summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/openjdkjvmti/OpenjdkJvmTi.cc2
-rw-r--r--runtime/openjdkjvmti/ti_class.cc44
-rw-r--r--runtime/openjdkjvmti/ti_class.h5
-rw-r--r--test/912-classes/classes.cc24
-rw-r--r--test/912-classes/expected.txt3
-rw-r--r--test/912-classes/src/Main.java9
6 files changed, 85 insertions, 2 deletions
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 98c4c3a511..5283919542 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -553,7 +553,7 @@ class JvmtiFunctions {
jclass klass,
jint* method_count_ptr,
jmethodID** methods_ptr) {
- return ERR(NOT_IMPLEMENTED);
+ return ClassUtil::GetClassMethods(env, klass, method_count_ptr, methods_ptr);
}
static jvmtiError GetClassFields(jvmtiEnv* env,
diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc
index 7b30a9da74..415e25857b 100644
--- a/runtime/openjdkjvmti/ti_class.cc
+++ b/runtime/openjdkjvmti/ti_class.cc
@@ -52,7 +52,6 @@ jvmtiError ClassUtil::GetClassFields(jvmtiEnv* env,
return ERR(NULL_POINTER);
}
- art::StackHandleScope<1> hs(soa.Self());
art::IterationRange<art::StrideIterator<art::ArtField>> ifields = klass->GetIFields();
art::IterationRange<art::StrideIterator<art::ArtField>> sfields = klass->GetSFields();
size_t array_size = klass->NumInstanceFields() + klass->NumStaticFields();
@@ -80,6 +79,49 @@ jvmtiError ClassUtil::GetClassFields(jvmtiEnv* env,
return ERR(NONE);
}
+jvmtiError ClassUtil::GetClassMethods(jvmtiEnv* env,
+ jclass jklass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr) {
+ art::ScopedObjectAccess soa(art::Thread::Current());
+ art::ObjPtr<art::mirror::Class> klass = soa.Decode<art::mirror::Class>(jklass);
+ if (klass == nullptr) {
+ return ERR(INVALID_CLASS);
+ }
+
+ if (method_count_ptr == nullptr || methods_ptr == nullptr) {
+ return ERR(NULL_POINTER);
+ }
+
+ size_t array_size = klass->NumDeclaredVirtualMethods() + klass->NumDirectMethods();
+ unsigned char* out_ptr;
+ jvmtiError allocError = env->Allocate(array_size * sizeof(jmethodID), &out_ptr);
+ if (allocError != ERR(NONE)) {
+ return allocError;
+ }
+ jmethodID* method_array = reinterpret_cast<jmethodID*>(out_ptr);
+
+ if (art::kIsDebugBuild) {
+ size_t count = 0;
+ for (auto& m ATTRIBUTE_UNUSED : klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
+ count++;
+ }
+ CHECK_EQ(count, klass->NumDirectMethods() + klass->NumDeclaredVirtualMethods());
+ }
+
+ size_t array_idx = 0;
+ for (auto& m : klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
+ method_array[array_idx] = art::jni::EncodeArtMethod(&m);
+ ++array_idx;
+ }
+
+ *method_count_ptr = static_cast<jint>(array_size);
+ *methods_ptr = method_array;
+
+ return ERR(NONE);
+}
+
+
jvmtiError ClassUtil::GetClassSignature(jvmtiEnv* env,
jclass jklass,
char** signature_ptr,
diff --git a/runtime/openjdkjvmti/ti_class.h b/runtime/openjdkjvmti/ti_class.h
index 5ee64be77a..838c94ceb4 100644
--- a/runtime/openjdkjvmti/ti_class.h
+++ b/runtime/openjdkjvmti/ti_class.h
@@ -44,6 +44,11 @@ class ClassUtil {
jint* field_count_ptr,
jfieldID** fields_ptr);
+ static jvmtiError GetClassMethods(jvmtiEnv* env,
+ jclass klass,
+ jint* method_count_ptr,
+ jmethodID** methods_ptr);
+
static jvmtiError GetClassSignature(jvmtiEnv* env,
jclass klass,
char** signature_ptr,
diff --git a/test/912-classes/classes.cc b/test/912-classes/classes.cc
index 28c5931521..6771d7183a 100644
--- a/test/912-classes/classes.cc
+++ b/test/912-classes/classes.cc
@@ -111,6 +111,30 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassFields(
return CreateObjectArray(env, count, "java/lang/Object", callback);
}
+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);
+ };
+ return CreateObjectArray(env, count, "java/lang/Object", callback);
+}
+
extern "C" JNIEXPORT jint JNICALL Java_Main_getClassStatus(
JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
jint status;
diff --git a/test/912-classes/expected.txt b/test/912-classes/expected.txt
index 44fed795ad..9999903647 100644
--- a/test/912-classes/expected.txt
+++ b/test/912-classes/expected.txt
@@ -15,6 +15,9 @@ java.lang.String interface=false array=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
diff --git a/test/912-classes/src/Main.java b/test/912-classes/src/Main.java
index 0b41113410..fd9e31aead 100644
--- a/test/912-classes/src/Main.java
+++ b/test/912-classes/src/Main.java
@@ -48,6 +48,10 @@ public class Main {
testClassFields(int.class);
testClassFields(String[].class);
+ testClassMethods(Integer.class);
+ testClassMethods(int.class);
+ testClassMethods(String[].class);
+
testClassStatus(int.class);
testClassStatus(String[].class);
testClassStatus(Object.class);
@@ -90,6 +94,10 @@ public class Main {
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)));
}
@@ -100,6 +108,7 @@ public class Main {
private static native boolean isArrayClass(Class<?> c);
private static native Object[] getClassFields(Class<?> c);
+ private static native Object[] getClassMethods(Class<?> c);
private static native int getClassStatus(Class<?> c);