Add support for GetClassVersionNumbers. Return the dex file version
as major, zero as minor. Add test.
Bug:
31684578
Test: m test-art-host-run-test-912-classes
Change-Id: Ib5082cd58b27a9183d8f19d42d4d8af46a6bb9c9
jclass klass,
jint* minor_version_ptr,
jint* major_version_ptr) {
- return ERR(NOT_IMPLEMENTED);
+ return ClassUtil::GetClassVersionNumbers(env, klass, minor_version_ptr, major_version_ptr);
}
static jvmtiError GetConstantPool(jvmtiEnv* env,
return ERR(NONE);
}
+jvmtiError ClassUtil::GetClassVersionNumbers(jvmtiEnv* env ATTRIBUTE_UNUSED,
+ jclass jklass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr) {
+ art::ScopedObjectAccess soa(art::Thread::Current());
+ if (jklass == nullptr) {
+ return ERR(INVALID_CLASS);
+ }
+ art::ObjPtr<art::mirror::Object> jklass_obj = soa.Decode<art::mirror::Object>(jklass);
+ if (!jklass_obj->IsClass()) {
+ return ERR(INVALID_CLASS);
+ }
+ art::ObjPtr<art::mirror::Class> klass = jklass_obj->AsClass();
+ if (klass->IsPrimitive() || klass->IsArrayClass()) {
+ return ERR(INVALID_CLASS);
+ }
+
+ if (minor_version_ptr == nullptr || major_version_ptr == nullptr) {
+ return ERR(NULL_POINTER);
+ }
+
+ // Note: proxies will show the dex file version of java.lang.reflect.Proxy, as that is
+ // what their dex cache copies from.
+ uint32_t version = klass->GetDexFile().GetHeader().GetVersion();
+
+ *major_version_ptr = static_cast<jint>(version);
+ *minor_version_ptr = 0;
+
+ return ERR(NONE);
+}
+
} // namespace openjdkjvmti
static jvmtiError IsInterface(jvmtiEnv* env, jclass klass, jboolean* is_interface_ptr);
static jvmtiError IsArrayClass(jvmtiEnv* env, jclass klass, jboolean* is_array_class_ptr);
+
+ static jvmtiError GetClassVersionNumbers(jvmtiEnv* env,
+ jclass klass,
+ jint* minor_version_ptr,
+ jint* major_version_ptr);
};
} // namespace openjdkjvmti
return ret;
}
+extern "C" JNIEXPORT jintArray JNICALL Java_Main_getClassVersion(
+ JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) {
+ jint major, minor;
+ jvmtiError result = jvmti_env->GetClassVersionNumbers(klass, &minor, &major);
+ if (JvmtiErrorToException(env, result)) {
+ return nullptr;
+ }
+
+ jintArray int_array = env->NewIntArray(2);
+ if (int_array == nullptr) {
+ return nullptr;
+ }
+ jint buf[2] = { major, minor };
+ env->SetIntArrayRegion(int_array, 0, 2, buf);
+
+ return int_array;
+}
+
} // namespace Test912Classes
} // namespace art
boot <- src+src-ex (A,B)
912-classes.jar+ ->
[class A, class B, class java.lang.Object]
+
+[37, 0]
testClassLoader(getProxyClass());
testClassLoaderClasses();
+
+ System.out.println();
+
+ testClassVersion();
}
private static Class<?> proxyClass = null;
}
}
+ private static void testClassVersion() {
+ System.out.println(Arrays.toString(getClassVersion(Main.class)));
+ }
+
private static void printClassLoaderClasses(ClassLoader cl) {
for (;;) {
if (cl == null || !cl.getClass().getName().startsWith("dalvik.system")) {
private static native Class<?>[] getClassLoaderClasses(ClassLoader cl);
+ private static native int[] getClassVersion(Class<?> c);
+
private static class TestForNonInit {
public static double dummy = Math.random(); // So it can't be compile-time initialized.
}