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

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

Reply via email to