author | attila |
Fri, 25 Apr 2014 14:20:07 +0200 | |
changeset 24205 | 0a7fbab84fb0 |
parent 22669 | 75563515567f |
child 24769 | de4dcfa9380f |
permissions | -rw-r--r-- |
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 | 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 | 34 |
import jdk.nashorn.internal.runtime.Context; |
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 | 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 | 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 | 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 | 62 |
StaticClass generateClass(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) { |
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 | 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 | 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 | 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 | 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 | 96 |
// should be able to refer to the few classes it needs in its implementation. |
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 | 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 |
} |