Permalink
Browse files

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).
  • Loading branch information...
1 parent 6014cb9 commit bead78d982fc231e0edfbb52315c6750963da3bd @dicej dicej committed Feb 23, 2011
Showing with 100 additions and 2 deletions.
  1. +4 −1 src/classpath-avian.cpp
  2. +34 −0 src/classpath-common.h
  3. +4 −1 src/classpath-openjdk.cpp
  4. +58 −0 test/Reflection.java
@@ -312,8 +312,11 @@ Avian_java_lang_reflect_Method_invoke
}
});
+ unsigned returnCode = methodReturnCode(t, method);
+
return reinterpret_cast<int64_t>
- (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
@@ -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
@@ -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<uint64_t>(makeLocalReference(t, result));
+ return reinterpret_cast<uint64_t>
+ (makeLocalReference(t, translateInvokeResult(t, returnCode, result)));
}
extern "C" JNIEXPORT jobject JNICALL
View
@@ -2,12 +2,70 @@
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");
Class output = Class.forName("java.io.PrintStream");
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));
}
}

0 comments on commit bead78d

Please sign in to comment.