From afbd4ff30303f6f205895d86e752f493b4a91e3c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 22 Jan 2015 11:52:23 -0700 Subject: [PATCH] fix crash when calling Class.getDeclaredMethods using the OpenJDK class library This method ends up defering to JVM_GetClassDeclaredMethods, which creates an array of java.lang.reflect.Method instances and then calling getName on each one through the java.lang.reflect.Member interface. However, Method is a "bootstrap" class, meaning the VM has built-in knowledge of it and includes a tentative version built-in but must load the real version from the classpath at runtime before invoking methods on it. Normally this happens naturally when Method instances are created in Java code, but here we're creating them in the VM instead, which doesn't automatically cause the real class to be loaded. So we must do so explicitly. --- src/classpath-openjdk.cpp | 13 +++++++++++++ test/UnsafeTest.java | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 4ec3c3c423..c19c7a6353 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2452,10 +2452,19 @@ object makeJconstructor(Thread* t, } #endif // HAVE_JexecutableHasRealParameterData +void resolveBootstrap(Thread* t, Gc::Type type) +{ + if (vm::type(t, type)->vmFlags() & BootstrapFlag) { + resolveSystemClass(t, roots(t)->bootLoader(), vm::type(t, type)->name()); + } +} + object makeJmethod(Thread* t, GcMethod* vmMethod, int index) { PROTECT(t, vmMethod); + resolveBootstrap(t, GcJmethod::Type); + object name = intern(t, t->m->classpath->makeString( @@ -2558,6 +2567,8 @@ object makeJconstructor(Thread* t, GcMethod* vmMethod, int index) { PROTECT(t, vmMethod); + resolveBootstrap(t, GcJconstructor::Type); + unsigned parameterCount; unsigned returnTypeSpec; object parameterTypes = resolveParameterJTypes(t, @@ -2638,6 +2649,8 @@ object makeJfield(Thread* t, GcField* vmField, int index) { PROTECT(t, vmField); + resolveBootstrap(t, GcJfield::Type); + object name = intern(t, t->m->classpath->makeString( diff --git a/test/UnsafeTest.java b/test/UnsafeTest.java index a644641dda..c7f4555773 100644 --- a/test/UnsafeTest.java +++ b/test/UnsafeTest.java @@ -135,6 +135,9 @@ public class UnsafeTest { } public static void main(String[] args) { + System.out.println("method count is " + + Unsafe.class.getDeclaredMethods().length); + Unsafe u = avian.Machine.getUnsafe(); unsafeCatch(u);