« Return to Thread: [rvm-research] A bug in reflection?

[rvm-research] A bug in reflection?

by Byeongcheol Lee :: Rate this Message:

Reply to Author | View in Thread


It appears that Jikes RVM has a bug in the implementation of its
reflection. For the detail, look at the patch and the test case:
reflection.patch and Reflection.java. Try the following.

1. To see the bug, try the following three command lines.

$javac ReflectionTest.java

$java -showversion ReflectionTest
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Server VM (build 11.0-b15, mixed mode)

newInstance: pass
invokeVirtual: pass
invokeStatic: pass

$rvm ReflectionTest
...
newInstance: pass
invokeVirtual: fail
unexpected cause of the Invocation target exception:
java.lang.reflect.InvocationTargetException
...
invokeStatic: fail
unexpected cause of the Invocation target exception:

2. To correct the bug, try the following.

  * Apply the patch: reflection.patch
  * Build Jikes RVM
  * Run it

$rvm ReflectionTest
newInstance: pass
invokeVirtual: pass
invokeStatic: pass

Cheers,
Byeong

[reflection.patch]

Index: libraryInterface/Common/src/java/lang/Class.java
===================================================================
--- libraryInterface/Common/src/java/lang/Class.java (revision 15651)
+++ libraryInterface/Common/src/java/lang/Class.java (working copy)
@@ -834,7 +834,7 @@
 
   @Inline(value=Inline.When.ArgumentsAreConstant, arguments={0})
   public T newInstance() throws IllegalAccessException, InstantiationException,
-    InvocationTargetException, ExceptionInInitializerError, SecurityException {
+    ExceptionInInitializerError, SecurityException {
 
     // Basic checks
     checkMemberAccess(Member.PUBLIC);
@@ -867,7 +867,14 @@
     T obj = (T)RuntimeEntrypoints.resolvedNewScalar(cls);
 
     // Run the default constructor on the it.
-    Reflection.invoke(defaultConstructor, null, obj, null, true);
+    try {
+      Reflection.invoke(defaultConstructor, null, obj, null, true);
+    } catch(InvocationTargetException e) {
+      // This suppresses compiler checking for the InvokeTargetException.
+      // Note that JDk 1.6 does not declare the InvokeTargetException for the newInstance
+      // method of the java.lang.Class.  
+      RuntimeEntrypoints.athrow(e.getCause());
+    }
 
     return obj;
   }
Index: libraryInterface/Common/src/java/lang/reflect/VMCommonLibrarySupport.java
===================================================================
--- libraryInterface/Common/src/java/lang/reflect/VMCommonLibrarySupport.java (revision 15651)
+++ libraryInterface/Common/src/java/lang/reflect/VMCommonLibrarySupport.java (working copy)
@@ -199,11 +199,7 @@
     }
 
     // Invoke method
-    try {
-      return Reflection.invoke(method, invoker, receiver, args, true);
-    } catch (Throwable t) {
-      throw new InvocationTargetException(t);
-    }
+    return Reflection.invoke(method, invoker, receiver, args, true);
   }
 
   @Inline(value=Inline.When.ArgumentsAreConstant, arguments={2})
@@ -229,11 +225,7 @@
     method = C.findVirtualMethod(method.getName(), method.getDescriptor());
 
     // Invoke method
-    try {
-      return Reflection.invoke(method, invoker, receiver, args, false);
-    } catch (Throwable t) {
-      throw new InvocationTargetException(t);
-    }
+    return Reflection.invoke(method, invoker, receiver, args, false);
   }
 
   @Inline(value=Inline.When.ArgumentsAreConstant, arguments={1})


[ReflectionTest.java]

import java.lang.reflect.*;

public class ReflectionTest {
  static class MyException extends RuntimeException {}

  public static void main(String[] args) {
    checkNewInstance();
    checkInvokeVirtual();
    checkInvokeStatic();
  }

  // "Note that this method propagates any exception thrown by the nullary
  // constructor, including a checked exception."
  // [http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance()]
  static void checkNewInstance() {
    try {
      ReflectionTest.class.newInstance();
    } catch(MyException e) {
      System.out.println("newInstance: pass");
    } catch(Throwable e) {
      System.out.println("newInstance: fail");
      System.out.println("  An unexpected expected exception thrown");
      e.printStackTrace();
    }
  }

  // For correct behavior, see the class description of the
  // following documentation:
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/InvocationTargetException.html
  static void checkInvokeVirtual() {
    try {
      ReflectionTest r = new ReflectionTest(0);
      Method mFoo = ReflectionTest.class.getMethod("foo");
      mFoo.invoke(r);
    } catch (InvocationTargetException e) {
      if (e.getCause() instanceof MyException) {
        System.out.println("invokeVirtual: pass");
      } else {        
        System.out.println("invokeVirtual: fail");
        System.out.println("unexpected cause of the Invocation target exception: ");
        e.printStackTrace();
      }
    } catch (Throwable e) {
      System.out.println("invokeVirtual: fail");
      System.out.println("  An unexpected expected exception thrown");
      e.printStackTrace();      
    }
  }

  // For correct behavior, see the class description of the
  // following documentation:
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)
  // http://java.sun.com/javase/6/docs/api/java/lang/reflect/InvocationTargetException.html
  static void checkInvokeStatic() {
    try {
      ReflectionTest r = new ReflectionTest(0);
      Method mFoo = ReflectionTest.class.getMethod("bar");
      mFoo.invoke(null);
    } catch (InvocationTargetException e) {
      if (e.getCause() instanceof MyException) {
        System.out.println("invokeStatic: pass");
      } else {        
        System.out.println("invokeStatic: fail");
        System.out.println("unexpected cause of the Invocation target exception: ");
        e.printStackTrace();
      }
    } catch (Throwable e) {
      System.out.println("invokeStatic: fail");
      System.out.println("  An unexpected expected exception thrown");
      e.printStackTrace();      
    }
  }

  public ReflectionTest() {throw new MyException();}
  public ReflectionTest(int i) {}
  public void foo() {throw new MyException();}
  public static void bar() {throw new MyException();}
}


------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Jikesrvm-researchers mailing list
Jikesrvm-researchers@...
https://lists.sourceforge.net/lists/listinfo/jikesrvm-researchers

 « Return to Thread: [rvm-research] A bug in reflection?