<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body style="background-color: rgb(255, 255, 255); color: rgb(0, 0,
    0);" bgcolor="#FFFFFF" text="#000000">
    Hi Max,<br>
    <br>
    <div class="moz-cite-prefix">On 03/30/2015 05:24 PM, Wang Weijun
      wrote:<br>
    </div>
    <blockquote
      cite="mid:9AC801D9-750C-4168-B1A6-76C16886E3A1@oracle.com"
      type="cite"><!--[if !IE]><DIV style="border-left: 2px solid #009900; border-right: 2px solid #009900;  padding: 0px 15px; margin: 2px 0px;"><![endif]-->
      <pre wrap="">I have a customized security manager:

import java.security.AccessController;
import java.security.PrivilegedAction;

public class A3 extends SecurityManager {
    public A3() {
        // 1. Using lambda
        AccessController.doPrivileged((PrivilegedAction<Void>)
                () -> null);
        // 2. Using inner class
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            @Override
            public Void run() {
                return null;
            }
        });
    }
}

If I use the inner class, everything is OK. If the lambda, I see this error:

$ java -Djava.security.manager=A3
Error occurred during initialization of VM
java.lang.ExceptionInInitializerError
        at java.lang.invoke.BoundMethodHandle.<clinit>(BoundMethodHandle.java:829)
        at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753)
        at java.lang.invoke.LambdaForm.<clinit>(LambdaForm.java:1808)
        at java.lang.invoke.DirectMethodHandle.makePreparedLambdaForm(DirectMethodHandle.java:223)
        at java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:188)
        at java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:177)
        at java.lang.invoke.DirectMethodHandle.make(DirectMethodHandle.java:84)
        at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1655)
        at java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:1612)
        at java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(MethodHandles.java:1797)
        at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1746)
        at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:477)
        at A3.<init>(A3.java:6)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:444)
        at sun.misc.Launcher.<init>(Launcher.java:96)
        at sun.misc.Launcher.<clinit>(Launcher.java:57)
        at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1440)
        at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1425)
Caused by: java.lang.NullPointerException
        at sun.invoke.util.BytecodeDescriptor.parseSig(BytecodeDescriptor.java:83)
        at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:54)
        at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:41)
        at java.lang.invoke.MethodType.fromMethodDescriptorString(MethodType.java:1065)
        at java.lang.invoke.BoundMethodHandle$Factory.makeCbmhCtor(BoundMethodHandle.java:817)
        at java.lang.invoke.BoundMethodHandle$Factory.makeCtors(BoundMethodHandle.java:772)
        at java.lang.invoke.BoundMethodHandle$SpeciesData.initForBootstrap(BoundMethodHandle.java:358)
        at java.lang.invoke.BoundMethodHandle$SpeciesData.<clinit>(BoundMethodHandle.java:447)
        at java.lang.invoke.BoundMethodHandle.<clinit>(BoundMethodHandle.java:829)
        at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753)
        at java.lang.invoke.LambdaForm.<clinit>(LambdaForm.java:1808)
        at java.lang.invoke.DirectMethodHandle.makePreparedLambdaForm(DirectMethodHandle.java:223)
        at java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:188)
        at java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:177)
        at java.lang.invoke.DirectMethodHandle.make(DirectMethodHandle.java:84)
        at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1655)
        at java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:1612)
        at java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(MethodHandles.java:1797)
        at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1746)
        at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:477)
        at A3.<init>(A3.java:6)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:444)

Any reason why?

Thanks
Max


</pre>
      <!--[if !IE]></DIV><![endif]--></blockquote>
    <br>
    I'm including mlvm-dev list because I think this is caused by
    unusual initialization sequence triggered by initialization of
    java.lang.invoke infrastructure because lambdas use invokedynamic
    and method handles. The part of stack trace that is interesting is
    this:<br>
    <br>
    <pre wrap="">Caused by: java.lang.NullPointerException
        at sun.invoke.util.BytecodeDescriptor.parseSig(BytecodeDescriptor.java:83)
        at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:54)
        at sun.invoke.util.BytecodeDescriptor.parseMethod(BytecodeDescriptor.java:41)
        at java.lang.invoke.MethodType.fromMethodDescriptorString(MethodType.java:1065)
        at java.lang.invoke.BoundMethodHandle$Factory.makeCbmhCtor(BoundMethodHandle.java:817)

</pre>
    makeCbmhCtor calls MethodType.fromMethodDescriptorString(..., null)
    with null ClassLoader, which propagates to the following
    BytecodeDescriptor.parseMethod method:<br>
    <br>
    <meta http-equiv="content-type" content="text/html;
      charset=windows-1252">
    <br>
    <tt>    static List<Class<?>> parseMethod(String
      bytecodeSignature,</tt><tt><br>
    </tt><tt>            int start, int end, ClassLoader loader) {</tt><tt><br>
    </tt><tt>        if (loader == null)</tt><tt><br>
    </tt><tt>            loader = ClassLoader.getSystemClassLoader();</tt><tt><br>
    </tt><tt>        String str = bytecodeSignature;</tt><tt><br>
    </tt><tt>        int[] i = {start};</tt><tt><br>
    </tt><tt>        ArrayList<Class<?>> ptypes = new
      ArrayList<Class<?>>();</tt><tt><br>
    </tt><tt>        if (i[0] < end && str.charAt(i[0]) ==
      '(') {</tt><tt><br>
    </tt><tt>            ++i[0];  // skip '('</tt><tt><br>
    </tt><tt>            while (i[0] < end &&
      str.charAt(i[0]) != ')') {</tt><tt><br>
    </tt><tt>                Class<?> pt = parseSig(str, i, end,
      loader);</tt><tt><br>
    </tt><tt>                if (pt == null || pt == void.class)</tt><tt><br>
    </tt><tt>                    parseError(str, "bad argument type");</tt><tt><br>
    </tt><tt>                ptypes.add(pt);</tt><tt><br>
    </tt><tt>            }</tt><tt><br>
    </tt><tt>            ++i[0];  // skip ')'</tt><tt><br>
    </tt><tt>        } else {</tt><tt><br>
    </tt><tt>            parseError(str, "not a method type");</tt><tt><br>
    </tt><tt>        }</tt><tt><br>
    </tt><tt>        Class<?> rtype = parseSig(str, i, end,
      loader);</tt><tt><br>
    </tt><tt>        if (rtype == null || i[0] != end)</tt><tt><br>
    </tt><tt>            parseError(str, "bad return type");</tt><tt><br>
    </tt><tt>        ptypes.add(rtype);</tt><tt><br>
    </tt><tt>        return ptypes;</tt><tt><br>
    </tt><tt>    }</tt><br>
    <br>
    <br>
    this method checks for null 'loader' and replaces it with the result
    of ClassLoader.getSystemClassLoader(). But invoking this method is
    actually re-entering it, as this whole stack trace is started from
    within the call to that method:<br>
    <br>
    <pre wrap="">        ....

        ....

        at sun.misc.Launcher.<init>(Launcher.java:96)
        at sun.misc.Launcher.<clinit>(Launcher.java:57)
        at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1440)
        at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1425)


</pre>
    ...this re-entering of ClassLoader.getSystemClassLoader() also
    re-enters Launcher.getLauncher():<br>
    <br>
    <br>
    <tt>    private static synchronized void initSystemClassLoader() {</tt><tt><br>
    </tt><tt>        if (!sclSet) {</tt><tt><br>
    </tt><tt>            if (scl != null)</tt><tt><br>
    </tt><tt>                throw new IllegalStateException("recursive
      invocation");</tt><tt><br>
    </tt><tt>            sun.misc.Launcher l =
      sun.misc.Launcher.getLauncher();</tt><tt><br>
    </tt><tt>            if (l != null) {</tt><tt><br>
    </tt><tt>                Throwable oops = null;</tt><tt><br>
    </tt><tt>                scl = l.getClassLoader();</tt><tt><br>
    </tt><tt>                try {</tt><tt><br>
    </tt><tt>                    scl = AccessController.doPrivileged(</tt><tt><br>
    </tt><tt>                        new SystemClassLoaderAction(scl));</tt><tt><br>
    </tt><tt>                } catch (PrivilegedActionException pae) {</tt><tt><br>
    </tt><tt>                    oops = pae.getCause();</tt><tt><br>
    </tt><tt>                    if (oops instanceof
      InvocationTargetException) {</tt><tt><br>
    </tt><tt>                        oops = oops.getCause();</tt><tt><br>
    </tt><tt>                    }</tt><tt><br>
    </tt><tt>                }</tt><tt><br>
    </tt><tt>                if (oops != null) {</tt><tt><br>
    </tt><tt>                    if (oops instanceof Error) {</tt><tt><br>
    </tt><tt>                        throw (Error) oops;</tt><tt><br>
    </tt><tt>                    } else {</tt><tt><br>
    </tt><tt>                        // wrap the exception</tt><tt><br>
    </tt><tt>                        throw new Error(oops);</tt><tt><br>
    </tt><tt>                    }</tt><tt><br>
    </tt><tt>                }</tt><tt><br>
    </tt><tt>            }</tt><tt><br>
    </tt><tt>            sclSet = true;</tt><tt><br>
    </tt><tt>        }</tt><tt><br>
    </tt><tt>    }</tt><br>
    <br>
    <br>
    ...which returns null and the whole initialization of 'scl' is
    skipped, therefore ClassLoader.getSystemClassLoader() returns null,
    which is later passed to BytecodeDescriptor.parseSig(...., null)
    which throws NPE when dereferencing it.<br>
    <br>
    <br>
    This re-entering of ClassLoader.getSystemClassLoader() is caused by
    Launcher which instantiates a custom SecurityManager, which uses
    lambdas which triggers java.lang.invoke infrastructure
    initialization which uses ClassLoader.getSystemClassLoader().<br>
    <br>
    I think that java.lang.invoke infrastructure initialization should
    not need to have access to system class loader. All types it deals
    with are loadable by bootstrap class loader. I too have already
    encountered a problem because of that and my suggestion was to
    create an internal method similar to
    MethodType.fromMethodDescriptorString() that would treat null
    ClassLoader as bootstrap class loader and use this method for
    internal initialization instead of the public one:<br>
    <br>
       
<a class="moz-txt-link-freetext" href="http://cr.openjdk.java.net/~plevart/jdk9-dev/MethodType.fromDescriptor/webrev.01/">http://cr.openjdk.java.net/~plevart/jdk9-dev/MethodType.fromDescriptor/webrev.01/</a><br>
    <br>
    With this patch, your A3 security manager using lambdas works
    normally.<br>
    <br>
    <br>
    Regards, Peter<br>
    <br>
  </body>
</html>