ART: Add GetMethodModifiers

Support GetMethodModifiers to retrieve the modifiers of a JNI
method.

Extend test 910.

Bug: 31684812
Test: m test-art-host-run-test-910-methods
Change-Id: Ib44df099bc056c557e526d5fa267df48ac2fd86c
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index f95ec59..9c3e4fc 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -654,7 +654,7 @@
   static jvmtiError GetMethodModifiers(jvmtiEnv* env,
                                        jmethodID method,
                                        jint* modifiers_ptr) {
-    return ERR(NOT_IMPLEMENTED);
+    return MethodUtil::GetMethodModifiers(env, method, modifiers_ptr);
   }
 
   static jvmtiError GetMaxLocals(jvmtiEnv* env,
diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc
index 4aae4d1..7b82e7c 100644
--- a/runtime/openjdkjvmti/ti_method.cc
+++ b/runtime/openjdkjvmti/ti_method.cc
@@ -34,6 +34,7 @@
 #include "art_jvmti.h"
 #include "art_method-inl.h"
 #include "base/enums.h"
+#include "modifiers.h"
 #include "scoped_thread_state_change-inl.h"
 
 namespace openjdkjvmti {
@@ -114,4 +115,30 @@
   return ERR(NONE);
 }
 
+jvmtiError MethodUtil::GetMethodModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED,
+                                          jmethodID method,
+                                          jint* modifiers_ptr) {
+  if (modifiers_ptr == nullptr) {
+    return ERR(NULL_POINTER);
+  }
+
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  art::ArtMethod* art_method = soa.DecodeMethod(method);
+
+  uint32_t modifiers = art_method->GetAccessFlags();
+
+  // Note: Keep this code in sync with Executable.fixMethodFlags.
+  if ((modifiers & art::kAccAbstract) != 0) {
+    modifiers &= ~art::kAccNative;
+  }
+  modifiers &= ~art::kAccSynchronized;
+  if ((modifiers & art::kAccDeclaredSynchronized) != 0) {
+    modifiers |= art::kAccSynchronized;
+  }
+  modifiers &= art::kAccJavaFlagsMask;
+
+  *modifiers_ptr = modifiers;
+  return ERR(NONE);
+}
+
 }  // namespace openjdkjvmti
diff --git a/runtime/openjdkjvmti/ti_method.h b/runtime/openjdkjvmti/ti_method.h
index 7cae0bf..43f11f9 100644
--- a/runtime/openjdkjvmti/ti_method.h
+++ b/runtime/openjdkjvmti/ti_method.h
@@ -48,6 +48,10 @@
   static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env,
                                             jmethodID method,
                                             jclass* declaring_class_ptr);
+
+  static jvmtiError GetMethodModifiers(jvmtiEnv* env,
+                                       jmethodID method,
+                                       jint* modifiers_ptr);
 };
 
 }  // namespace openjdkjvmti
diff --git a/test/910-methods/expected.txt b/test/910-methods/expected.txt
index 980edc3..9a74799 100644
--- a/test/910-methods/expected.txt
+++ b/test/910-methods/expected.txt
@@ -1,10 +1,15 @@
 [toString, ()Ljava/lang/String;, null]
 class java.lang.Object
+1
 [charAt, (I)C, null]
 class java.lang.String
+257
 [sqrt, (D)D, null]
 class java.lang.Math
+265
 [add, (Ljava/lang/Object;)Z, null]
 interface java.util.List
+1025
 [run, ()V, null]
 class $Proxy0
+17
diff --git a/test/910-methods/methods.cc b/test/910-methods/methods.cc
index 214ae50..cc6ad67 100644
--- a/test/910-methods/methods.cc
+++ b/test/910-methods/methods.cc
@@ -91,6 +91,22 @@
   return declaring_class;
 }
 
+extern "C" JNIEXPORT jint JNICALL Java_Main_getMethodModifiers(
+    JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject method) {
+  jmethodID id = env->FromReflectedMethod(method);
+
+  jint modifiers;
+  jvmtiError result = jvmti_env->GetMethodModifiers(id, &modifiers);
+  if (result != JVMTI_ERROR_NONE) {
+    char* err;
+    jvmti_env->GetErrorName(result, &err);
+    printf("Failure running GetMethodModifiers: %s\n", err);
+    return 0;
+  }
+
+  return modifiers;
+}
+
 // 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 d8c4627..3459134 100644
--- a/test/910-methods/src/Main.java
+++ b/test/910-methods/src/Main.java
@@ -62,8 +62,15 @@
       throw new RuntimeException("Declaring class not equal: " + base + " vs " + declClass);
     }
     System.out.println(declClass);
+
+    int modifiers = getMethodModifiers(m);
+    if (modifiers != m.getModifiers()) {
+      throw new RuntimeException("Modifiers not equal: " + m.getModifiers() + " vs " + modifiers);
+    }
+    System.out.println(modifiers);
   }
 
   private static native String[] getMethodName(Method m);
   private static native Class<?> getMethodDeclaringClass(Method m);
+  private static native int getMethodModifiers(Method m);
 }