From weijun.wang at oracle.com Mon Mar 30 15:24:24 2015 From: weijun.wang at oracle.com (Wang Weijun) Date: Mon, 30 Mar 2015 23:24:24 +0800 Subject: Lambda in security manager initialization fail Message-ID: <9AC801D9-750C-4168-B1A6-76C16886E3A1@oracle.com> 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) () -> null); // 2. Using inner class AccessController.doPrivileged(new PrivilegedAction() { @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.(BoundMethodHandle.java:829) at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753) at java.lang.invoke.LambdaForm.(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.(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.(Launcher.java:96) at sun.misc.Launcher.(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.(BoundMethodHandle.java:447) at java.lang.invoke.BoundMethodHandle.(BoundMethodHandle.java:829) at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753) at java.lang.invoke.LambdaForm.(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.(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 From peter.levart at gmail.com Mon Mar 30 20:01:42 2015 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 30 Mar 2015 22:01:42 +0200 Subject: Lambda in security manager initialization fail In-Reply-To: <9AC801D9-750C-4168-B1A6-76C16886E3A1@oracle.com> References: <9AC801D9-750C-4168-B1A6-76C16886E3A1@oracle.com> Message-ID: <5519ABA6.2030409@gmail.com> Hi Max, On 03/30/2015 05:24 PM, Wang Weijun wrote: > 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) > () -> null); > // 2. Using inner class > AccessController.doPrivileged(new PrivilegedAction() { > @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.(BoundMethodHandle.java:829) > at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753) > at java.lang.invoke.LambdaForm.(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.(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.(Launcher.java:96) > at sun.misc.Launcher.(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.(BoundMethodHandle.java:447) > at java.lang.invoke.BoundMethodHandle.(BoundMethodHandle.java:829) > at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753) > at java.lang.invoke.LambdaForm.(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.(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 > > 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: 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) makeCbmhCtor calls MethodType.fromMethodDescriptorString(..., null) with null ClassLoader, which propagates to the following BytecodeDescriptor.parseMethod method: static List> parseMethod(String bytecodeSignature, int start, int end, ClassLoader loader) { if (loader == null) loader = ClassLoader.getSystemClassLoader(); String str = bytecodeSignature; int[] i = {start}; ArrayList> ptypes = new ArrayList>(); if (i[0] < end && str.charAt(i[0]) == '(') { ++i[0]; // skip '(' while (i[0] < end && str.charAt(i[0]) != ')') { Class pt = parseSig(str, i, end, loader); if (pt == null || pt == void.class) parseError(str, "bad argument type"); ptypes.add(pt); } ++i[0]; // skip ')' } else { parseError(str, "not a method type"); } Class rtype = parseSig(str, i, end, loader); if (rtype == null || i[0] != end) parseError(str, "bad return type"); ptypes.add(rtype); return ptypes; } 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: .... .... at sun.misc.Launcher.(Launcher.java:96) at sun.misc.Launcher.(Launcher.java:57) at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1440) at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1425) ...this re-entering of ClassLoader.getSystemClassLoader() also re-enters Launcher.getLauncher(): private static synchronized void initSystemClassLoader() { if (!sclSet) { if (scl != null) throw new IllegalStateException("recursive invocation"); sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); if (l != null) { Throwable oops = null; scl = l.getClassLoader(); try { scl = AccessController.doPrivileged( new SystemClassLoaderAction(scl)); } catch (PrivilegedActionException pae) { oops = pae.getCause(); if (oops instanceof InvocationTargetException) { oops = oops.getCause(); } } if (oops != null) { if (oops instanceof Error) { throw (Error) oops; } else { // wrap the exception throw new Error(oops); } } } sclSet = true; } } ...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. 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(). 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: http://cr.openjdk.java.net/~plevart/jdk9-dev/MethodType.fromDescriptor/webrev.01/ With this patch, your A3 security manager using lambdas works normally. Regards, Peter From brian.goetz at oracle.com Mon Mar 30 20:12:43 2015 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 30 Mar 2015 16:12:43 -0400 Subject: Lambda in security manager initialization fail In-Reply-To: <9AC801D9-750C-4168-B1A6-76C16886E3A1@oracle.com> References: <9AC801D9-750C-4168-B1A6-76C16886E3A1@oracle.com> Message-ID: <5519AE3B.9050300@oracle.com> The NPE is at BytecodeDescriptor.parseSig#83, which says: return loader.loadClass(name); so the null ref seems likely to be loader. The loader is initially passed in from BoundMethodHandle#817, which provides a null loader, indicating that it wants the system loader. At the start of parseMethod, we see: if (loader == null) loader = ClassLoader.getSystemClassLoader(); so the loader variable that is being deref'ed is the result of ClassLoader.getSystemClassLoader, which must be null in order to NPE here. ClassLoader.getSystemClassLoader checks for a security manager, but since you're still initializing the security manager, this is likely to be null. So you're going to get the value of `scl` after `initSystemClassLoader` has completed. Overall this smells of a bootstrapping issue; you're calling into the MH machinery possibly before the classloading machinery (and definitely before the security manager) is fully initialized, and you're getting back a null from ClassLoader.getSystemClassLoader. HTH, -Brian On 3/30/2015 11:24 AM, Wang Weijun wrote: > 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) > () -> null); > // 2. Using inner class > AccessController.doPrivileged(new PrivilegedAction() { > @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.(BoundMethodHandle.java:829) > at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753) > at java.lang.invoke.LambdaForm.(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.(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.(Launcher.java:96) > at sun.misc.Launcher.(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.(BoundMethodHandle.java:447) > at java.lang.invoke.BoundMethodHandle.(BoundMethodHandle.java:829) > at java.lang.invoke.LambdaForm.createIdentityForms(LambdaForm.java:1753) > at java.lang.invoke.LambdaForm.(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.(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 > > From Alan.Bateman at oracle.com Mon Mar 30 20:29:54 2015 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Mon, 30 Mar 2015 21:29:54 +0100 Subject: Lambda in security manager initialization fail In-Reply-To: <5519ABA6.2030409@gmail.com> References: <9AC801D9-750C-4168-B1A6-76C16886E3A1@oracle.com> <5519ABA6.2030409@gmail.com> Message-ID: <5519B242.1070403@oracle.com> On 30/03/2015 21:01, Peter Levart wrote: > : > > 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: > > http://cr.openjdk.java.net/~plevart/jdk9-dev/MethodType.fromDescriptor/webrev.01/ > > > With this patch, your A3 security manager using lambdas works normally. Another one that has come once or twice is using method references in code that executes early in the startup. There are boxing cases that use TypeConvertingMethodAdapter.boxingDescriptor and hence the formatter code that tries to locate locale providers using the system class loader. This can lead to recursive initialization issues that pop out as BootstrapMethodError. So if we are making this area more robust then this might need to be looked at too. -Alan