Merge pull request #118 from dicej/master

fix exception wrapping for Method.invoke and static initializers
This commit is contained in:
Joshua Warner 2013-12-06 07:13:41 -08:00
commit d17bbc6d1b
6 changed files with 70 additions and 6 deletions

View File

@ -11,11 +11,11 @@
package java.lang; package java.lang;
public class ExceptionInInitializerError extends Error { public class ExceptionInInitializerError extends Error {
private final Throwable cause2; private final Throwable exception;
public ExceptionInInitializerError(String message) { public ExceptionInInitializerError(String message) {
super(message); super(message);
cause2 = null; exception = null;
} }
public ExceptionInInitializerError() { public ExceptionInInitializerError() {

View File

@ -84,6 +84,8 @@ public class Field<T> extends AccessibleObject {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
Classes.initialize(vmField.class_);
switch (vmField.code) { switch (vmField.code) {
case ByteField: case ByteField:
return Byte.valueOf return Byte.valueOf
@ -171,6 +173,8 @@ public class Field<T> extends AccessibleObject {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
Classes.initialize(vmField.class_);
switch (vmField.code) { switch (vmField.code) {
case ByteField: case ByteField:
setPrimitive(target, vmField.code, vmField.offset, (Byte) value); setPrimitive(target, vmField.code, vmField.offset, (Byte) value);
@ -235,6 +239,8 @@ public class Field<T> extends AccessibleObject {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
Classes.initialize(vmField.class_);
switch (vmField.code) { switch (vmField.code) {
case ByteField: case ByteField:
case BooleanField: case BooleanField:

View File

@ -81,6 +81,8 @@ public class Method<T> extends AccessibleObject implements Member {
} }
if (arguments.length == vmMethod.parameterCount) { if (arguments.length == vmMethod.parameterCount) {
Classes.initialize(vmMethod.class_);
return invoke(vmMethod, instance, arguments); return invoke(vmMethod, instance, arguments);
} else { } else {
throw new ArrayIndexOutOfBoundsException(); throw new ArrayIndexOutOfBoundsException();

View File

@ -567,13 +567,14 @@ invoke(Thread* t, object method, object instance, object args)
} }
} }
initClass(t, methodClass(t, method));
unsigned returnCode = methodReturnCode(t, method); unsigned returnCode = methodReturnCode(t, method);
THREAD_RESOURCE0(t, { THREAD_RESOURCE0(t, {
if (t->exception) { if (t->exception) {
object exception = t->exception;
t->exception = makeThrowable t->exception = makeThrowable
(t, Machine::InvocationTargetExceptionType, 0, 0, exception); (t, Machine::InvocationTargetExceptionType, 0, 0, t->exception);
set(t, t->exception, InvocationTargetExceptionTarget, set(t, t->exception, InvocationTargetExceptionTarget,
throwableCause(t, t->exception)); throwableCause(t, t->exception));

View File

@ -4534,8 +4534,13 @@ postInitClass(Thread* t, object c)
object exception = t->exception; object exception = t->exception;
t->exception = 0; t->exception = 0;
throwNew(t, Machine::ExceptionInInitializerErrorType, exception = makeThrowable
static_cast<object>(0), 0, exception); (t, Machine::ExceptionInInitializerErrorType, 0, 0, exception);
set(t, exception, ExceptionInInitializerErrorException,
throwableCause(t, exception));
throw_(t, exception);
} else { } else {
classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag); classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag);
} }

View File

@ -2,6 +2,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.lang.reflect.InvocationTargetException;
public class Reflection { public class Reflection {
public static boolean booleanMethod() { public static boolean booleanMethod() {
@ -92,6 +93,10 @@ public class Reflection {
expect(args[0] == String.class); expect(args[0] == String.class);
} }
public static void throwOOME() {
throw new OutOfMemoryError();
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
innerClasses(); innerClasses();
annotations(); annotations();
@ -130,5 +135,50 @@ public class Reflection {
expect("[Ljava.lang.Class;".equals(array[0].getClass().getName())); expect("[Ljava.lang.Class;".equals(array[0].getClass().getName()));
expect(Class[].class == array[0].getClass()); expect(Class[].class == array[0].getClass());
expect(array.getClass().getComponentType() == array[0].getClass()); expect(array.getClass().getComponentType() == array[0].getClass());
try {
Foo.class.getMethod("foo").invoke(null);
expect(false);
} catch (ExceptionInInitializerError e) {
expect(e.getCause() instanceof MyException);
}
try {
Foo.class.getConstructor().newInstance();
expect(false);
} catch (NoClassDefFoundError e) {
// cool
}
try {
Foo.class.getField("foo").get(null);
expect(false);
} catch (NoClassDefFoundError e) {
// cool
}
{ Method m = Reflection.class.getMethod("throwOOME");
try {
m.invoke(null);
} catch(Throwable t) {
expect(t.getClass() == InvocationTargetException.class);
}
}
} }
} }
class Foo {
static {
if (true) throw new MyException();
}
public Foo() { }
public static int foo;
public static void foo() {
// ignore
}
}
class MyException extends RuntimeException { }