nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
author attila
Fri, 25 Apr 2014 14:20:07 +0200
changeset 24205 0a7fbab84fb0
parent 22669 75563515567f
child 24769 de4dcfa9380f
permissions -rw-r--r--
8034967: Reduce access to Nashorn internals Reviewed-by: ahgross, jlaskey, sundar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     1
/*
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     2
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     4
 *
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    10
 *
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    15
 * accompanied this code).
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    16
 *
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    20
 *
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    23
 * questions.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    24
 */
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    25
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    26
package jdk.nashorn.internal.runtime.linker;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    27
19459
79e75274df99 8022707: Revisit all doPrivileged blocks
sundar
parents: 19456
diff changeset
    28
import java.security.AccessControlContext;
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    29
import java.security.AccessController;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    30
import java.security.PrivilegedAction;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    31
import java.security.ProtectionDomain;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    32
import java.security.SecureClassLoader;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    33
import jdk.internal.dynalink.beans.StaticClass;
24205
0a7fbab84fb0 8034967: Reduce access to Nashorn internals
attila
parents: 22669
diff changeset
    34
import jdk.nashorn.internal.runtime.Context;
0a7fbab84fb0 8034967: Reduce access to Nashorn internals
attila
parents: 22669
diff changeset
    35
import jdk.nashorn.internal.runtime.ScriptFunction;
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    36
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    37
/**
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    38
 * This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    39
 * It can be invoked repeatedly to create multiple adapter classes from the same bytecode; adapter classes that have
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    40
 * class-level overrides must be re-created for every set of such overrides. Note that while this class is named
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    41
 * "class loader", it does not, in fact, extend {@code ClassLoader}, but rather uses them internally. Instances of this
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    42
 * class are normally created by {@link JavaAdapterBytecodeGenerator}.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    43
 */
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 16777
diff changeset
    44
@SuppressWarnings("javadoc")
19085
066c9e5afd79 8020731: Revisit checkPermission calls in Context class
sundar
parents: 17769
diff changeset
    45
final class JavaAdapterClassLoader {
19459
79e75274df99 8022707: Revisit all doPrivileged blocks
sundar
parents: 19456
diff changeset
    46
    private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    47
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    48
    private final String className;
22669
75563515567f 8032681: Issues with Nashorn
attila
parents: 19627
diff changeset
    49
    private final byte[] classBytes;
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    50
19085
066c9e5afd79 8020731: Revisit checkPermission calls in Context class
sundar
parents: 17769
diff changeset
    51
    JavaAdapterClassLoader(String className, byte[] classBytes) {
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    52
        this.className = className.replace('/', '.');
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    53
        this.classBytes = classBytes;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    54
    }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    55
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    56
    /**
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    57
     * Loads the generated adapter class into the JVM.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    58
     * @param parentLoader the parent class loader for the generated class loader
22669
75563515567f 8032681: Issues with Nashorn
attila
parents: 19627
diff changeset
    59
     * @param protectionDomain the protection domain for the generated class
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    60
     * @return the generated adapter class
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    61
     */
22669
75563515567f 8032681: Issues with Nashorn
attila
parents: 19627
diff changeset
    62
    StaticClass generateClass(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) {
75563515567f 8032681: Issues with Nashorn
attila
parents: 19627
diff changeset
    63
        assert protectionDomain != null;
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    64
        return AccessController.doPrivileged(new PrivilegedAction<StaticClass>() {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    65
            @Override
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    66
            public StaticClass run() {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    67
                try {
22669
75563515567f 8032681: Issues with Nashorn
attila
parents: 19627
diff changeset
    68
                    return StaticClass.forClass(Class.forName(className, true, createClassLoader(parentLoader, protectionDomain)));
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    69
                } catch (final ClassNotFoundException e) {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    70
                    throw new AssertionError(e); // cannot happen
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    71
                }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    72
            }
19459
79e75274df99 8022707: Revisit all doPrivileged blocks
sundar
parents: 19456
diff changeset
    73
        }, CREATE_LOADER_ACC_CTXT);
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    74
    }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    75
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    76
    // Note that the adapter class is created in the protection domain of the class/interface being
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    77
    // extended/implemented, and only the privileged global setter action class is generated in the protection domain
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    78
    // of Nashorn itself. Also note that the creation and loading of the global setter is deferred until it is
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    79
    // required by JVM linker, which will only happen on first invocation of any of the adapted method. We could defer
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    80
    // it even more by separating its invocation into a separate static method on the adapter class, but then someone
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    81
    // with ability to introspect on the class and use setAccessible(true) on it could invoke the method. It's a
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    82
    // security tradeoff...
22669
75563515567f 8032681: Issues with Nashorn
attila
parents: 19627
diff changeset
    83
    private ClassLoader createClassLoader(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) {
19097
f544a2ea40ef 8021262: Make nashorn access checks consistent with underlying dynalink
sundar
parents: 19085
diff changeset
    84
        return new SecureClassLoader(parentLoader) {
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    85
            private final ClassLoader myLoader = getClass().getClassLoader();
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    86
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    87
            @Override
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    88
            public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    89
                try {
24205
0a7fbab84fb0 8034967: Reduce access to Nashorn internals
attila
parents: 22669
diff changeset
    90
                    Context.checkPackageAccess(name);
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    91
                    return super.loadClass(name, resolve);
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    92
                } catch (final SecurityException se) {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    93
                    // we may be implementing an interface or extending a class that was
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    94
                    // loaded by a loader that prevents package.access. If so, it'd throw
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    95
                    // SecurityException for nashorn's classes!. For adapter's to work, we
24205
0a7fbab84fb0 8034967: Reduce access to Nashorn internals
attila
parents: 22669
diff changeset
    96
                    // should be able to refer to the few classes it needs in its implementation.
0a7fbab84fb0 8034967: Reduce access to Nashorn internals
attila
parents: 22669
diff changeset
    97
                    if(ScriptFunction.class.getName().equals(name) || JavaAdapterServices.class.getName().equals(name)) {
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    98
                        return myLoader.loadClass(name);
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
    99
                    }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   100
                    throw se;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   101
                }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   102
            }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   103
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   104
            @Override
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   105
            protected Class<?> findClass(final String name) throws ClassNotFoundException {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   106
                if(name.equals(className)) {
19456
8cc345d620c8 8022524: Memory leaks in nashorn sources and tests found by jhat analysis
sundar
parents: 19097
diff changeset
   107
                    assert classBytes != null : "what? already cleared .class bytes!!";
22669
75563515567f 8032681: Issues with Nashorn
attila
parents: 19627
diff changeset
   108
                    return defineClass(name, classBytes, 0, classBytes.length, protectionDomain);
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   109
                }
19472
9476460521b3 8023017: SUB missing for widest op == number for BinaryNode
lagergren
parents: 19459
diff changeset
   110
                throw new ClassNotFoundException(name);
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   111
            }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   112
        };
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   113
    }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents:
diff changeset
   114
}