Hi Peter, IMHO such security manager usage by the test is v. fragile and we should try and find a safer alternative if possible.
However, there may also be an issue with lambda form code. (About a month ago i too was looking, internally, at this kind of issue and thought there was a questionable use of the application/system class loader when initializing the LambdaForm class, but then i got distracted with other stuff and forgot about it.) Your one-liner fix seems to do the trick, but I think we need Vladimir to confirm this is OK. Paul. On Apr 17, 2014, at 11:49 PM, Peter Levart <peter.lev...@gmail.com> wrote: > Hi, > > I'm cross-posting this on the mlvm-dev mailing list, because I think it > concerns internal MHs implementation. > > While replacing some inner classes with lambdas in java.lang.UNIXProcess > class, a jtreg test started failing. This test is employing a security > manager with an unusual configuration. It defines "java.util" as a package > for which access should be checked against the set of permissions. The class > initialization of UNIXProcess class initializes some lambdas and their > initialization fails with the following stack-trace: > > > java.lang.ExceptionInInitializerError > at > java.lang.invoke.DirectMethodHandle.makePreparedLambdaForm(DirectMethodHandle.java:256) > at > java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:221) > at > java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:210) > at java.lang.invoke.DirectMethodHandle.make(DirectMethodHandle.java:82) > at > java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:1638) > at > java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:1602) > at > java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(MethodHandles.java:1778) > at > java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1727) > at > java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:442) > at java.lang.UNIXProcess$Platform.get(UNIXProcess.java:147) > at java.lang.UNIXProcess.<clinit>(UNIXProcess.java:160) > at java.lang.ProcessImpl.start(ProcessImpl.java:130) > at java.lang.ProcessBuilder.start(ProcessBuilder.java:1023) > at java.lang.Runtime.exec(Runtime.java:620) > at java.lang.Runtime.exec(Runtime.java:485) > at SecurityManagerClinit.main(SecurityManagerClinit.java:70) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > at > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > at java.lang.reflect.Method.invoke(Method.java:484) > at > com.sun.javatest.regtest.MainWrapper$MainThread.run(MainWrapper.java:94) > at java.lang.Thread.run(Thread.java:744) > Caused by: java.security.AccessControlException: access denied > ("java.lang.RuntimePermission" "accessClassInPackage.java.util") > at > java.security.AccessControlContext.checkPermission(AccessControlContext.java:457) > at > java.security.AccessController.checkPermission(AccessController.java:884) > at java.lang.SecurityManager.checkPermission(SecurityManager.java:541) > at > java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1481) > * at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:305)* > at java.lang.ClassLoader.loadClass(ClassLoader.java:359) > 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:911) > at java.lang.invoke.MemberName.getMethodType(MemberName.java:144) > at > java.lang.invoke.LambdaForm.computeInitialPreparedForms(LambdaForm.java:477) > at java.lang.invoke.LambdaForm.<clinit>(LambdaForm.java:1641) > > > I think I found the root cause of the problem. It's nothing wrong with the > test (although making "java.util" as an access-checked package is a little > unusual). The problem, I think, is in MH's LambdaForm implementation. > Although the UNIXProcess class is a system class (loaded by bootstrap class > loader), MHs created by evaluating lambda expressions in this class, trigger > loading a class in "java.util" package using AppClassLoader as the initiating > class loader, which involves package access checks. This should not happen, I > think, if only the system classes are involved in constructing MHs. > > I checked the code and there's a ClassLoader parameter passed to the > *BytecodeDescriptor.parseMethod *method. This ClassLoader is taken as the > defining class loader of the MemberName's declaring class for which the > getMethoType() is requested. All the types involved in such MemberName > (return type, parameter types) should be resolvable from the MemberName's > declaring class' class loader. In our case, the class loader of the declaring > class of the particular MemberName is bootstrap class loader, so null is > passed as the ClassLoader parameter to the *BytecodeDescriptor.parseMethod > *method. This method checks for null ClassLoader and replaces it with > ClassLoader.getSystemClassLoader() before calling parseSig() with it, because > parseSig() uses the ClassLoader instance to invoke loadClass() method on it. > The ClassLoader.getSystemClassLoader() is the application class-loader > (AppClassLoader). > > I think the right thing to do would be to use bootstrap class loader if the > ClassLoader parameter passed to *BytecodeDescriptor.parseMethod *was null. > The fix would be as follows: > > > =================================================================== > --- jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java (revision > 9770:8371276d52c0) > +++ jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java (revision > 9770+:8371276d52c0+) > @@ -43,8 +43,6 @@ > > static List<Class<?>> parseMethod(String bytecodeSignature, > int start, int end, ClassLoader loader) { > - if (loader == null) > - loader = ClassLoader.getSystemClassLoader(); > String str = bytecodeSignature; > int[] i = {start}; > ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>(); > @@ -80,7 +78,7 @@ > i[0] = endc+1; > String name = str.substring(begc, endc).replace('/', '.'); > try { > - return loader.loadClass(name); > + return Class.forName(name, false, loader); > } catch (ClassNotFoundException ex) { > throw new TypeNotPresentException(name, ex); > } > > > > What do you think? Am I right? > > > Regards, Peter
signature.asc
Description: Message signed with OpenPGP using GPGMail
_______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev