diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 95b2a3270..9efba455e 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -312,8 +312,11 @@ Avian_java_lang_reflect_Method_invoke } }); + unsigned returnCode = methodReturnCode(t, method); + return reinterpret_cast - (t->m->processor->invokeArray(t, method, instance, args)); + (translateInvokeResult + (t, returnCode, t->m->processor->invokeArray(t, method, instance, args))); } extern "C" JNIEXPORT int64_t JNICALL diff --git a/src/classpath-common.h b/src/classpath-common.h index 6efc0a142..8c89f94cf 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -286,6 +286,40 @@ makeStackTraceElement(Thread* t, object e) return makeStackTraceElement(t, class_, method, file, line); } +object +translateInvokeResult(Thread* t, unsigned returnCode, object o) +{ + switch (returnCode) { + case ByteField: + return makeByte(t, intValue(t, o)); + + case BooleanField: + return makeBoolean(t, intValue(t, o) != 0); + + case CharField: + return makeChar(t, intValue(t, o)); + + case ShortField: + return makeShort(t, intValue(t, o)); + + case FloatField: + return makeFloat(t, intValue(t, o)); + + case IntField: + case LongField: + case ObjectField: + case VoidField: + return o; + + case DoubleField: + return makeDouble(t, longValue(t, o)); + break; + + default: + abort(t); + } +} + } // namespace vm #endif//CLASSPATH_COMMON_H diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index ab7ba6117..6e432d54d 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3162,6 +3162,8 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) instance = 0; } + unsigned returnCode = methodReturnCode(t, vmMethod); + object result; if (args) { result = t->m->processor->invokeArray @@ -3170,7 +3172,8 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) result = t->m->processor->invoke(t, vmMethod, instance ? *instance : 0); } - return reinterpret_cast(makeLocalReference(t, result)); + return reinterpret_cast + (makeLocalReference(t, translateInvokeResult(t, returnCode, result))); } extern "C" JNIEXPORT jobject JNICALL diff --git a/test/Reflection.java b/test/Reflection.java index 71a70db81..f71b39e81 100644 --- a/test/Reflection.java +++ b/test/Reflection.java @@ -2,6 +2,42 @@ import java.lang.reflect.Field; public class Reflection { + public static boolean booleanMethod() { + return true; + } + + public static byte byteMethod() { + return 1; + } + + public static char charMethod() { + return '2'; + } + + public static short shortMethod() { + return 3; + } + + public static int intMethod() { + return 4; + } + + public static float floatMethod() { + return 5.0f; + } + + public static long longMethod() { + return 6; + } + + public static double doubleMethod() { + return 7.0; + } + + public static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + public static void main(String[] args) throws Exception { Class system = Class.forName("java.lang.System"); Field out = system.getDeclaredField("out"); @@ -9,5 +45,27 @@ public static void main(String[] args) throws Exception { Method println = output.getDeclaredMethod("println", String.class); println.invoke(out.get(null), "Hello, World!"); + + expect((Boolean) Reflection.class.getMethod("booleanMethod").invoke(null)); + + expect(1 == (Byte) Reflection.class.getMethod("byteMethod").invoke(null)); + + expect('2' == (Character) Reflection.class.getMethod + ("charMethod").invoke(null)); + + expect(3 == (Short) Reflection.class.getMethod + ("shortMethod").invoke(null)); + + expect(4 == (Integer) Reflection.class.getMethod + ("intMethod").invoke(null)); + + expect(5.0 == (Float) Reflection.class.getMethod + ("floatMethod").invoke(null)); + + expect(6 == (Long) Reflection.class.getMethod + ("longMethod").invoke(null)); + + expect(7.0 == (Double) Reflection.class.getMethod + ("doubleMethod").invoke(null)); } }