From bead78d982fc231e0edfbb52315c6750963da3bd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 22 Feb 2011 17:54:56 -0700 Subject: [PATCH] wrap primitive return values using correct types in Method.invoke The VM uses Integer and Long instances internally to wrap the results of dynamic method invocations, but Method.invoke should use the correct, specific type for the primitive (e.g. Character for char). --- src/classpath-avian.cpp | 5 +++- src/classpath-common.h | 34 +++++++++++++++++++++++ src/classpath-openjdk.cpp | 5 +++- test/Reflection.java | 58 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 95b2a32703..9efba455e4 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 6efc0a1424..8c89f94cf6 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 ab7ba61179..6e432d54d2 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 71a70db815..f71b39e81b 100644 --- a/test/Reflection.java +++ b/test/Reflection.java @@ -2,6 +2,42 @@ import java.lang.reflect.Method; 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 class Reflection { 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)); } }