Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7044892

JSR 292: API entry points sometimes throw the wrong exceptions or doesn't throw the expected one

XMLWordPrintable

    • b144
    • generic
    • generic
    • Verified

      MethodHandles$Lookup.findStatic[S|G]etter throws InternalError if SecurityManager is set.

      Minimized test:
      ===============
      $ cat test.java
      import java.lang.invoke.*;

      public class test {
          public static void main(String[] args) throws Throwable {
              System.setSecurityManager(new SM());

              MethodHandle mh = MethodHandles.lookup().findStaticSetter(
                      GetSet.class, "sf1", int.class);
          }
      }

      class SM extends SecurityManager {
          protected SM() { super(); }
      }

      class GetSet {
          static int sf1;
      }

      Minimized test output:
      ======================
      $ javac test.java

      $ java -showversion test
      java version "1.7.0-ea"
      Java(TM) SE Runtime Environment (build 1.7.0-ea-b140)
      Java HotSpot(TM) Server VM (build 21.0-b10, mixed mode)

      Exception in thread "main" java.lang.InternalError: uncaught exception
              at java.lang.invoke.MethodHandleStatics.uncaughtException(MethodHandleStatics.java:84)
              at java.lang.invoke.MethodHandleImpl$FieldAccessor.staticBase(MethodHandleImpl.java:314)
              at java.lang.invoke.MethodHandleImpl$FieldAccessor.<init>(MethodHandleImpl.java:278)
              at java.lang.invoke.MethodHandleImpl.accessField(MethodHandleImpl.java:241)
              at java.lang.invoke.MethodHandles$Lookup.makeAccessor(MethodHandles.java:1103)
              at java.lang.invoke.MethodHandles$Lookup.makeAccessor(MethodHandles.java:1094)
              at java.lang.invoke.MethodHandles$Lookup.findStaticSetter(MethodHandles.java:785)
              at test.main(test.java:7)
      Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
              at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
              at java.security.AccessController.checkPermission(AccessController.java:555)
              at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
              at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1679)
              at java.lang.Class.checkMemberAccess(Class.java:2174)
              at java.lang.Class.getDeclaredField(Class.java:1896)
              at java.lang.invoke.MethodHandleImpl$FieldAccessor.staticBase(MethodHandleImpl.java:311)
              ... 6 more
      MethodHandle.invoke[Exact|Generic] doesn't throw UnsupportedOperationException if invoked via java.lang.reflect.Method.invoke.

      The javadoc for the MethodHandle invokeExact/invokeGeneric methods states as follows:
        "When this method is observed via the Core Reflection API, it will appear as a single
        native method, taking an object array and returning an object. If this native method
        is invoked directly via Method.invoke ... it will throw an UnsupportedOperationException."

      However, InvocationTargetException is thrown in such cases.

      Minimized test:
      ===============
      $ cat test.java
      import java.lang.reflect.*;
      import java.lang.invoke.*;

      public class test {
          public static void main(String[] args) throws Throwable {
              MethodHandle target = MethodHandles.lookup().findVirtual(
                      MethodHandle.class, "invokeExact",
                      MethodType.methodType(Object.class, Object[].class));
              Method method = MethodHandle.class.getDeclaredMethod(
                      "invokeExact", Object[].class);
              //Method method = MethodHandle.class.getDeclaredMethod(
              // "invokeGeneric", Object[].class);

              Object[] params = new Object[1];
              method.invoke(target, params);
          }
      }

      Minimized test output:
      ========================
      $ javac test.java
      $ java -verify test
      Exception in thread "main" java.lang.reflect.InvocationTargetException
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.lang.reflect.Method.invoke(Method.java:601)
              at test.main(test.java:15)
      Caused by: java.lang.UnsatisfiedLinkError: java.lang.invoke.MethodHandle.invokeExact([Ljava/lang/Object;)Ljava/lang/Object;
              at java.lang.invoke.MethodHandle.invokeExact(Native Method)
              ... 5 more
      MethodType.methodType(Class rtype, Class[] ptypes) doesn't throw NPE if ptypes is null.

      Minimized test:
      ===============
      $ cat Test.java
      import java.lang.invoke.*;
      import java.util.Arrays;

      public class Test {
          public static void main(String[] args) throws Exception {
              Object[][] data = new Object[][] {
                  { (Class) null, (Class[]) null },
                  { (Class) null, new Class[]{Object.class} },
                  { Object.class, new Class[]{ null} },
                  { Object.class, new Class[]{Object.class, (Class) null} },
                  { Object.class, (Class[]) null }
              };

              for (int i = 0; i < data.length; i++) {
                  Class<?> rtype = (Class) data[i][0];
                  Class<?>[] ptypes = (Class[]) data[i][1];
                  try {
                      MethodType.methodType(rtype, ptypes);
                      System.out.println("FAILED: NPE not thrown for " + rtype + ", " + Arrays.toString(ptypes));
                  } catch(NullPointerException ok) {
                      System.out.println("OK: NPE is thrown for " + rtype + ", " + Arrays.toString(ptypes));
                  }
              }
          }
      }

      Minimized test output:
      ========================
      $ java -showversion -verify Test
      java version "1.7.0-ea"
      Java(TM) SE Runtime Environment (build 1.7.0-ea-b138)
      Java HotSpot(TM) Server VM (build 21.0-b08, mixed mode)

      OK: NPE is thrown for null, null
      OK: NPE is thrown for null, [class java.lang.Object]
      OK: NPE is thrown for class java.lang.Object, [null]
      OK: NPE is thrown for class java.lang.Object, [class java.lang.Object, null]
      FAILED: NPE not thrown for class java.lang.Object, null
      MethodType.fromMethodDescriptorString unexpectedly accepts both "binary names"/"internal form of binary names".

      Minimized test:
      ===============
      $ cat Test.java
      import java.lang.invoke.*;

      public class Test {
          public static void main(String[] args) throws Exception {
              for (String d : new String[] {"(Ljava/lang/Object;)V", "(Ljava.lang.Object;)V"}) {
                  MethodType.fromMethodDescriptorString(d, null);
                  System.out.println("OK");
              }
          }
      }

      Minimized test output:
      ======================
      $ java -showversion -verify Test
      java version "1.7.0-ea"
      Java(TM) SE Runtime Environment (build 1.7.0-ea-b138)
      Java HotSpot(TM) Server VM (build 21.0-b08, mixed mode)

      OK
      OK
      MethodHandles.Lookup.find[G|S]etter throws unexpected IllegalAccessException.

      Minimized test:
      ===============
      $ cat test.java
      import java.lang.invoke.MethodType;
      import static java.lang.invoke.MethodHandles.*;
      import static java.lang.invoke.MethodHandles.Lookup.*;

      public class test {

          public static void main(String[] args) throws Throwable {
              lookup().findGetter(TestCls.class, "f2", int.class);
              TestCls c = new TestCls();
              c.f2 = 1;
          }
      }

      class TestCls {
          protected int f2 = 2;
      }

      Minimized test output:
      ======================
      $ java -showversion test
      java version "1.7.0-ea"
      Java(TM) SE Runtime Environment (build 1.7.0-ea-b140)
      Java HotSpot(TM) Server VM (build 21.0-b10, mixed mode)

      Exception in thread "main" java.lang.IllegalAccessException: caller class must be a subclass below the method: TestCls.f2/int, from class test
              at java.lang.invoke.MemberName.makeAccessException(MemberName.java:507)
              at java.lang.invoke.MethodHandles$Lookup.restrictReceiver(MethodHandles.java:1078)
              at java.lang.invoke.MethodHandles$Lookup.restrictProtectedReceiver(MethodHandles.java:1072)
              at java.lang.invoke.MethodHandles$Lookup.makeAccessor(MethodHandles.java:1104)
              at java.lang.invoke.MethodHandles$Lookup.makeAccessor(MethodHandles.java:1094)
              at java.lang.invoke.MethodHandles$Lookup.findGetter(MethodHandles.java:724)
              at test.main(test.java:8)
      MethodHandle.asCollector throws undocumented ArrayIndexOutOfBoundsException instead of IllegalArgumentException for invalid arrayLength values (negative or >= 256).

      Minimized test:
      ===============
      $ cat test.java
      import java.lang.invoke.*;
      import java.util.Arrays;

      public class test {
          public static void main(String[] args) throws Throwable {
              MethodHandle dts = MethodHandles.publicLookup().findStatic(
                      Arrays.class,
                      "deepToString",
                      MethodType.methodType(String.class, Object[].class));
              dts.asCollector(Object[].class, -1);
          }
      }

      Minimized test output:
      ======================
      $ openjdk7-mlvm/solaris-i586/bin/java -verify test
      Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
              at sun.invoke.util.ValueConversions.varargsArray(ValueConversions.java:1068)
              at sun.invoke.util.ValueConversions.varargsArray(ValueConversions.java:1144)
              at java.lang.invoke.MethodHandle.asCollector(MethodHandle.java:872)
              at test.main(test.java:10)
      MethodHandle.bindTo((Object) null) throws InternalError.

      Minimized test:
      ===============
      $ cat test.java
      import java.lang.invoke.*;
      import static java.lang.invoke.MethodHandles.*;
      import static java.lang.invoke.MethodType.*;

      public class test {

          public static void main(String[] args) throws Throwable {
              MethodHandle target = publicLookup().findVirtual(
                      String.class, "toString", methodType(String.class));
              MethodHandle bt = target.bindTo((Object) null);
          }
      }

      Minimized test output:
      ======================
      $ java -verify test
      Exception in thread "main" java.lang.InternalError
              at java.lang.invoke.MethodHandleNatives.init(Native Method)
              at java.lang.invoke.BoundMethodHandle.initTarget(BoundMethodHandle.java:81)
              at java.lang.invoke.BoundMethodHandle.<init>(BoundMethodHandle.java:76)
              at java.lang.invoke.BoundMethodHandle.<init>(BoundMethodHandle.java:61)
              at java.lang.invoke.MethodHandleImpl.bindReceiver(MethodHandleImpl.java:501)
              at java.lang.invoke.MethodHandle.bindTo(MethodHandle.java:1125)
              at test.main(test.java:10)

            jrose John Rose
            ygaevsky Yuri Gaevsky (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: