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).
This commit is contained in:
Joel Dice 2011-02-22 17:54:56 -07:00
parent 6014cb93b1
commit bead78d982
4 changed files with 100 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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 File

@ -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));
}
}