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