mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-19 11:26:43 +00:00
Merge
This commit is contained in:
commit
9dd34d95e0
@ -3,7 +3,7 @@ The GNU General Public License (GPL)
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
@ -287,8 +287,8 @@ pointer to where the full notice is found.
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
||||
@ -258,31 +258,13 @@
|
||||
<property name="compile.suppress.jar" value="defined"/>
|
||||
</target>
|
||||
|
||||
<!-- generate javadoc for all Nashorn and ASM classes -->
|
||||
<!-- generate javadoc for Nashorn classes -->
|
||||
<target name="javadoc" depends="jar">
|
||||
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
|
||||
windowtitle="${nashorn.product.name} ${nashorn.version}"
|
||||
additionalparam="-quiet" failonerror="true" useexternalfile="true">
|
||||
<arg value="${javadoc.option}"/>
|
||||
<classpath>
|
||||
<pathelement location="${build.classes.dir}"/>
|
||||
</classpath>
|
||||
<fileset dir="${nashorn.module.src.dir}" includes="**/*.java"/>
|
||||
<fileset dir="${nashorn.shell.module.src.dir}" includes="**/*.java"/>
|
||||
<fileset dir="${jdk.asm.src.dir}" includes="**/*.java"/>
|
||||
<link href="http://docs.oracle.com/javase/8/docs/api/"/>
|
||||
<!-- The following tags are used only in ASM sources - just ignore these -->
|
||||
<tag name="label" description="label tag in ASM sources" enabled="false"/>
|
||||
<tag name="linked" description="linked tag in ASM sources" enabled="false"/>
|
||||
<tag name="associates" description="associates tag in ASM sources" enabled="false"/>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<!-- generate javadoc for Nashorn classes -->
|
||||
<target name="javadocnh" depends="jar">
|
||||
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
|
||||
windowtitle="${nashorn.product.name} ${nashorn.version}"
|
||||
additionalparam="-quiet" failonerror="true" useexternalfile="true">
|
||||
<arg value="-modulesourcepath"/>
|
||||
<arg value="${basedir}/src/*/share/classes"/>
|
||||
<arg value="${javadoc.option}"/>
|
||||
<classpath>
|
||||
<pathelement location="${build.classes.dir}"/>
|
||||
@ -295,10 +277,13 @@
|
||||
</target>
|
||||
|
||||
<!-- generate javadoc only for nashorn extension api classes -->
|
||||
<target name="javadocapi" depends="jar">
|
||||
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
|
||||
<target name="nashornapi" depends="jar">
|
||||
<mkdir dir="${dist.nashornapi.javadoc.dir}"/>
|
||||
<javadoc destdir="${dist.nashornapi.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
|
||||
extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
|
||||
additionalparam="-quiet" failonerror="true" useexternalfile="true">
|
||||
<arg value="-modulesourcepath"/>
|
||||
<arg value="${basedir}/src/*/share/classes"/>
|
||||
<arg value="${javadoc.option}"/>
|
||||
<classpath>
|
||||
<pathelement location="${build.classes.dir}"/>
|
||||
@ -310,9 +295,12 @@
|
||||
|
||||
<!-- generate javadoc only for Dynalink API classes -->
|
||||
<target name="dynalinkapi" depends="jar">
|
||||
<javadoc destdir="${dist.javadoc.dir}" use="yes"
|
||||
<mkdir dir="${dist.dynalinkapi.javadoc.dir}"/>
|
||||
<javadoc destdir="${dist.dynalinkapi.javadoc.dir}" use="yes"
|
||||
windowtitle="Dynalink"
|
||||
additionalparam="-quiet" failonerror="true" useexternalfile="true">
|
||||
<arg value="-modulesourcepath"/>
|
||||
<arg value="${basedir}/src/*/share/classes"/>
|
||||
<arg value="${javadoc.option}"/>
|
||||
<classpath>
|
||||
<pathelement location="${build.classes.dir}"/>
|
||||
@ -322,6 +310,8 @@
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<target name="javadocapi" depends="nashornapi, dynalinkapi"/>
|
||||
|
||||
<!-- generate shell.html for shell tool documentation -->
|
||||
<target name="shelldoc" depends="jar">
|
||||
<java classname="${nashorn.shell.tool}" dir="${basedir}" output="${dist.dir}/shell.html" failonerror="true" fork="true">
|
||||
@ -502,6 +492,10 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" {
|
||||
permission java.io.FilePermission "${basedir}/test/script/external/showdown/-", "read";
|
||||
};
|
||||
|
||||
grant codeBase "file:/${basedir}/test/script/basic/JDK-8158467.js" {
|
||||
permission java.lang.RuntimePermission "nashorn.setConfig";
|
||||
};
|
||||
|
||||
</echo>
|
||||
|
||||
<replace file="${build.dir}/nashorn.policy"><replacetoken>\</replacetoken><replacevalue>/</replacevalue></replace> <!--hack for Windows - to make URLs with normal path separators -->
|
||||
@ -595,7 +589,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" {
|
||||
</testng>
|
||||
</target>
|
||||
|
||||
<target name="test" depends="prepare, test-pessimistic, test-optimistic"/>
|
||||
<target name="test" depends="prepare, javadoc, test-pessimistic, test-optimistic"/>
|
||||
|
||||
<target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
|
||||
<echo message="Running test suite in OPTIMISTIC mode..."/>
|
||||
|
||||
@ -24,7 +24,8 @@
|
||||
application.title=nashorn
|
||||
|
||||
# location of JDK embedded ASM sources
|
||||
jdk.asm.src.dir=../jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm
|
||||
jdk.java.base.dir=../jdk/src/java.base/share/classes
|
||||
jdk.asm.src.dir=${jdk.java.base.dir}/jdk/internal/org/objectweb/asm
|
||||
|
||||
# location of JDK embedded jline sources
|
||||
jdk.jline.src.dir=../jdk/src/jdk.internal.le/share/classes
|
||||
@ -86,6 +87,8 @@ dynalink.jar=${dist.dir}/dynalink.jar
|
||||
nashorn.jar=${dist.dir}/nashorn.jar
|
||||
jjs.jar=${dist.dir}/jjs.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
dist.nashornapi.javadoc.dir=${dist.javadoc.dir}/nashornapi
|
||||
dist.dynalinkapi.javadoc.dir=${dist.javadoc.dir}/dynalinkapi
|
||||
|
||||
# configuration for java flight recorder
|
||||
run.test.jvmargs.jfr=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128
|
||||
|
||||
@ -44,7 +44,7 @@ public final class Module {
|
||||
/**
|
||||
* A module ExportEntry record.
|
||||
*
|
||||
* @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
|
||||
* @see <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records">es6 modules</a>
|
||||
*/
|
||||
public static final class ExportEntry {
|
||||
private final String exportName;
|
||||
@ -164,7 +164,7 @@ public final class Module {
|
||||
/**
|
||||
* An ImportEntry record.
|
||||
*
|
||||
* @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
|
||||
* @see <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records">es6 modules</a>
|
||||
*/
|
||||
public static final class ImportEntry {
|
||||
private final String moduleRequest;
|
||||
|
||||
@ -4626,6 +4626,9 @@ public class Parser extends AbstractParser implements Loggable {
|
||||
* ArrowFunction[?In, ?Yield]
|
||||
* LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
|
||||
* LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
|
||||
*
|
||||
* @param noIn {@code true} if IN operator should be ignored.
|
||||
* @return the assignment expression
|
||||
*/
|
||||
protected Expression assignmentExpression(final boolean noIn) {
|
||||
// This method is protected so that subclass can get details
|
||||
|
||||
@ -39,14 +39,21 @@ import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Module;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.AccessControlContext;
|
||||
@ -60,9 +67,12 @@ import java.security.PrivilegedExceptionAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@ -128,6 +138,11 @@ public final class Context {
|
||||
*/
|
||||
public static final String NASHORN_JAVA_REFLECTION = "nashorn.JavaReflection";
|
||||
|
||||
/**
|
||||
* Permission to create a new Module
|
||||
*/
|
||||
public static final String NASHORN_CREATE_MODULE = "nashorn.createModule";
|
||||
|
||||
/**
|
||||
* Permission to enable nashorn debug mode.
|
||||
*/
|
||||
@ -337,7 +352,7 @@ public final class Context {
|
||||
return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
|
||||
}
|
||||
|
||||
private static final byte[] getAnonymousHostClassBytes() {
|
||||
private static byte[] getAnonymousHostClassBytes() {
|
||||
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cw.visit(V1_7, Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, ANONYMOUS_HOST_CLASS_NAME.replace('.', '/'), null, "java/lang/Object", null);
|
||||
cw.visitEnd();
|
||||
@ -471,6 +486,11 @@ public final class Context {
|
||||
/** class loader to resolve classes from script. */
|
||||
private final ClassLoader appLoader;
|
||||
|
||||
/*package-private*/
|
||||
ClassLoader getAppLoader() {
|
||||
return appLoader;
|
||||
}
|
||||
|
||||
/** Class loader to load classes compiled from scripts. */
|
||||
private final ScriptLoader scriptLoader;
|
||||
|
||||
@ -486,13 +506,13 @@ public final class Context {
|
||||
/** Optional class filter to use for Java classes. Can be null. */
|
||||
private final ClassFilter classFilter;
|
||||
|
||||
private static final ClassLoader myLoader = Context.class.getClassLoader();
|
||||
private static final StructureLoader sharedLoader;
|
||||
/** Process-wide singleton structure loader */
|
||||
private static final StructureLoader theStructLoader;
|
||||
private static final ConcurrentMap<String, Class<?>> structureClasses = new ConcurrentHashMap<>();
|
||||
|
||||
/*package-private*/ @SuppressWarnings("static-method")
|
||||
StructureLoader getSharedLoader() {
|
||||
return sharedLoader;
|
||||
StructureLoader getStructLoader() {
|
||||
return theStructLoader;
|
||||
}
|
||||
|
||||
private static AccessControlContext createNoPermAccCtxt() {
|
||||
@ -508,9 +528,11 @@ public final class Context {
|
||||
private static final AccessControlContext NO_PERMISSIONS_ACC_CTXT = createNoPermAccCtxt();
|
||||
private static final AccessControlContext CREATE_LOADER_ACC_CTXT = createPermAccCtxt("createClassLoader");
|
||||
private static final AccessControlContext CREATE_GLOBAL_ACC_CTXT = createPermAccCtxt(NASHORN_CREATE_GLOBAL);
|
||||
private static final AccessControlContext GET_LOADER_ACC_CTXT = createPermAccCtxt("getClassLoader");
|
||||
|
||||
static {
|
||||
sharedLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() {
|
||||
final ClassLoader myLoader = Context.class.getClassLoader();
|
||||
theStructLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() {
|
||||
@Override
|
||||
public StructureLoader run() {
|
||||
return new StructureLoader(myLoader);
|
||||
@ -791,7 +813,7 @@ public final class Context {
|
||||
// Nashorn extension: any 'eval' is unconditionally strict when -strict is specified.
|
||||
boolean strictFlag = strict || this._strict;
|
||||
|
||||
Class<?> clazz = null;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = compile(source, new ThrowErrorManager(), strictFlag, true);
|
||||
} catch (final ParserException e) {
|
||||
@ -1022,7 +1044,7 @@ public final class Context {
|
||||
}
|
||||
return (Class<? extends ScriptObject>)structureClasses.computeIfAbsent(fullName, (name) -> {
|
||||
try {
|
||||
return Class.forName(name, true, sharedLoader);
|
||||
return Class.forName(name, true, theStructLoader);
|
||||
} catch (final ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
@ -1144,7 +1166,17 @@ public final class Context {
|
||||
}
|
||||
|
||||
// Try finding using the "app" loader.
|
||||
return Class.forName(fullName, true, appLoader);
|
||||
if (appLoader != null) {
|
||||
return Class.forName(fullName, true, appLoader);
|
||||
} else {
|
||||
final Class<?> cl = Class.forName(fullName);
|
||||
// return the Class only if it was loaded by boot loader
|
||||
if (cl.getClassLoader() == null) {
|
||||
return cl;
|
||||
} else {
|
||||
throw new ClassNotFoundException(fullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1175,7 +1207,7 @@ public final class Context {
|
||||
// No verification when security manager is around as verifier
|
||||
// may load further classes - which should be avoided.
|
||||
if (System.getSecurityManager() == null) {
|
||||
CheckClassAdapter.verify(new ClassReader(bytecode), sharedLoader, false, new PrintWriter(System.err, true));
|
||||
CheckClassAdapter.verify(new ClassReader(bytecode), theStructLoader, false, new PrintWriter(System.err, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1281,6 +1313,78 @@ public final class Context {
|
||||
return getContextTrusted().dynamicLinker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a module layer with one module that is defined to the given class
|
||||
* loader.
|
||||
*
|
||||
* @param descriptor the module descriptor for the newly created module
|
||||
* @param loader the class loader of the module
|
||||
* @return the new Module
|
||||
*/
|
||||
public static Module createModule(final ModuleDescriptor descriptor, final ClassLoader loader) {
|
||||
final SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new RuntimePermission(NASHORN_CREATE_MODULE));
|
||||
}
|
||||
return createModuleTrusted(descriptor, loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a module layer with one module that is defined to the given class
|
||||
* loader.
|
||||
*
|
||||
* @param descriptor the module descriptor for the newly created module
|
||||
* @param loader the class loader of the module
|
||||
* @return the new Module
|
||||
*/
|
||||
static Module createModuleTrusted(final ModuleDescriptor descriptor, final ClassLoader loader) {
|
||||
return createModuleTrusted(Layer.boot(), descriptor, loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a module layer with one module that is defined to the given class
|
||||
* loader.
|
||||
*
|
||||
* @param parent the parent layer of the new module
|
||||
* @param descriptor the module descriptor for the newly created module
|
||||
* @param loader the class loader of the module
|
||||
* @return the new Module
|
||||
*/
|
||||
static Module createModuleTrusted(final Layer parent, final ModuleDescriptor descriptor, final ClassLoader loader) {
|
||||
final String mn = descriptor.name();
|
||||
|
||||
final ModuleReference mref = new ModuleReference(descriptor, null, () -> {
|
||||
IOException ioe = new IOException("<dynamic module>");
|
||||
throw new UncheckedIOException(ioe);
|
||||
});
|
||||
|
||||
final ModuleFinder finder = new ModuleFinder() {
|
||||
@Override
|
||||
public Optional<ModuleReference> find(String name) {
|
||||
if (name.equals(mn)) {
|
||||
return Optional.of(mref);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Set<ModuleReference> findAll() {
|
||||
return Set.of(mref);
|
||||
}
|
||||
};
|
||||
|
||||
final Configuration cf = parent.configuration()
|
||||
.resolveRequires(finder, ModuleFinder.of(), Set.of(mn));
|
||||
|
||||
final PrivilegedAction<Layer> pa = () -> parent.defineModules(cf, name -> loader);
|
||||
final Layer layer = AccessController.doPrivileged(pa, GET_LOADER_ACC_CTXT);
|
||||
|
||||
final Module m = layer.findModule(mn).get();
|
||||
assert m.getLayer() == layer;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static Context getContextTrustedOrNull() {
|
||||
final Global global = Context.getGlobal();
|
||||
return global == null ? null : getContext(global);
|
||||
@ -1463,7 +1567,7 @@ public final class Context {
|
||||
new PrivilegedAction<ScriptLoader>() {
|
||||
@Override
|
||||
public ScriptLoader run() {
|
||||
return new ScriptLoader(appLoader, Context.this);
|
||||
return new ScriptLoader(Context.this);
|
||||
}
|
||||
}, CREATE_LOADER_ACC_CTXT);
|
||||
}
|
||||
|
||||
@ -26,19 +26,22 @@
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.lang.reflect.Module;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permission;
|
||||
import java.security.PermissionCollection;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.Permissions;
|
||||
import java.security.SecureClassLoader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import jdk.internal.module.Modules;
|
||||
|
||||
/**
|
||||
* Superclass for Nashorn class loader classes.
|
||||
@ -55,15 +58,14 @@ abstract class NashornLoader extends SecureClassLoader {
|
||||
protected static final String RUNTIME_LINKER_PKG_INTERNAL = "jdk/nashorn/internal/runtime/linker";
|
||||
protected static final String SCRIPTS_PKG_INTERNAL = "jdk/nashorn/internal/scripts";
|
||||
|
||||
protected static final Module nashornModule = NashornLoader.class.getModule();
|
||||
static final Module NASHORN_MODULE = Context.class.getModule();
|
||||
|
||||
private static final Permission[] SCRIPT_PERMISSIONS;
|
||||
|
||||
private static final Set<String> scriptsPkgSet = new HashSet<>();
|
||||
private static final String MODULE_MANIPULATOR_NAME = SCRIPTS_PKG + ".ModuleGraphManipulator";
|
||||
private static final byte[] MODULE_MANIPULATOR_BYTES = readModuleManipulatorBytes();
|
||||
|
||||
static {
|
||||
scriptsPkgSet.add(SCRIPTS_PKG);
|
||||
|
||||
/*
|
||||
* Generated classes get access to runtime, runtime.linker, objects, scripts packages.
|
||||
* Note that the actual scripts can not access these because Java.type, Packages
|
||||
@ -80,23 +82,42 @@ abstract class NashornLoader extends SecureClassLoader {
|
||||
};
|
||||
}
|
||||
|
||||
// addExport Method object on ModuleGraphManipulator
|
||||
// class loaded by this loader
|
||||
private Method addModuleExport;
|
||||
|
||||
NashornLoader(final ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
protected static Module defineModule(final String moduleName, final ClassLoader loader) {
|
||||
return Modules.defineModule(loader, moduleName, scriptsPkgSet);
|
||||
void loadModuleManipulator() {
|
||||
final Class<?> clazz = defineClass(MODULE_MANIPULATOR_NAME,
|
||||
MODULE_MANIPULATOR_BYTES, 0, MODULE_MANIPULATOR_BYTES.length);
|
||||
// force class initialization so that <clinit> runs!
|
||||
try {
|
||||
Class.forName(MODULE_MANIPULATOR_NAME, true, this);
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
final PrivilegedAction<Void> pa = () -> {
|
||||
try {
|
||||
addModuleExport = clazz.getDeclaredMethod("addExport", Module.class);
|
||||
addModuleExport.setAccessible(true);
|
||||
} catch (final NoSuchMethodException | SecurityException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
AccessController.doPrivileged(pa);
|
||||
}
|
||||
|
||||
protected static void addReadsModule(final Module from, final Module to) {
|
||||
Modules.addReads(from, to);
|
||||
}
|
||||
|
||||
protected static void addModuleExports(final Module from, final String pkg, final Module to) {
|
||||
if (to == null) {
|
||||
Modules.addExportsToAll(from, pkg);
|
||||
} else {
|
||||
Modules.addExports(from, pkg, to);
|
||||
final void addModuleExport(final Module to) {
|
||||
try {
|
||||
addModuleExport.invoke(null, to);
|
||||
} catch (final IllegalAccessException |
|
||||
IllegalArgumentException |
|
||||
InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,5 +215,17 @@ abstract class NashornLoader extends SecureClassLoader {
|
||||
throw new IllegalArgumentException("file");
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] readModuleManipulatorBytes() {
|
||||
final PrivilegedAction<byte[]> pa = () -> {
|
||||
final String res = "/"+ MODULE_MANIPULATOR_NAME.replace('.', '/') + ".class";
|
||||
try (InputStream in = NashornLoader.class.getResourceAsStream(res)) {
|
||||
return in.readAllBytes();
|
||||
} catch (IOException exp) {
|
||||
throw new UncheckedIOException(exp);
|
||||
}
|
||||
};
|
||||
return AccessController.doPrivileged(pa);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.reflect.Module;
|
||||
import java.security.CodeSource;
|
||||
import java.util.Objects;
|
||||
@ -37,8 +38,8 @@ final class ScriptLoader extends NashornLoader {
|
||||
private static final String NASHORN_PKG_PREFIX = "jdk.nashorn.internal.";
|
||||
|
||||
private volatile boolean structureAccessAdded;
|
||||
private final Module scriptModule;
|
||||
private final Context context;
|
||||
private final Module scriptModule;
|
||||
|
||||
/*package-private*/ Context getContext() {
|
||||
return context;
|
||||
@ -47,44 +48,77 @@ final class ScriptLoader extends NashornLoader {
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
ScriptLoader(final ClassLoader parent, final Context context) {
|
||||
super(parent);
|
||||
ScriptLoader(final Context context) {
|
||||
super(context.getStructLoader());
|
||||
this.context = context;
|
||||
|
||||
// new scripts module, it's specific exports and read-edges
|
||||
scriptModule = defineModule("jdk.scripting.nashorn.scripts", this);
|
||||
addModuleExports(scriptModule, SCRIPTS_PKG, nashornModule);
|
||||
addReadsModule(scriptModule, nashornModule);
|
||||
addReadsModule(scriptModule, Object.class.getModule());
|
||||
scriptModule = createModule("jdk.scripting.nashorn.scripts");
|
||||
|
||||
// specific exports from nashorn to new scripts module
|
||||
nashornModule.addExports(OBJECTS_PKG, scriptModule);
|
||||
nashornModule.addExports(RUNTIME_PKG, scriptModule);
|
||||
nashornModule.addExports(RUNTIME_ARRAYS_PKG, scriptModule);
|
||||
nashornModule.addExports(RUNTIME_LINKER_PKG, scriptModule);
|
||||
nashornModule.addExports(SCRIPTS_PKG, scriptModule);
|
||||
NASHORN_MODULE.addExports(OBJECTS_PKG, scriptModule);
|
||||
NASHORN_MODULE.addExports(RUNTIME_PKG, scriptModule);
|
||||
NASHORN_MODULE.addExports(RUNTIME_ARRAYS_PKG, scriptModule);
|
||||
NASHORN_MODULE.addExports(RUNTIME_LINKER_PKG, scriptModule);
|
||||
NASHORN_MODULE.addExports(SCRIPTS_PKG, scriptModule);
|
||||
|
||||
// nashorn needs to read scripts module methods,fields
|
||||
nashornModule.addReads(scriptModule);
|
||||
NASHORN_MODULE.addReads(scriptModule);
|
||||
}
|
||||
|
||||
private Module createModule(final String moduleName) {
|
||||
final Module structMod = context.getStructLoader().getModule();
|
||||
final ModuleDescriptor descriptor
|
||||
= new ModuleDescriptor.Builder(moduleName)
|
||||
.requires(NASHORN_MODULE.getName())
|
||||
.requires(structMod.getName())
|
||||
.conceals(SCRIPTS_PKG)
|
||||
.build();
|
||||
|
||||
final Module mod = Context.createModuleTrusted(structMod.getLayer(), descriptor, this);
|
||||
loadModuleManipulator();
|
||||
return mod;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
|
||||
checkPackageAccess(name);
|
||||
if (name.startsWith(NASHORN_PKG_PREFIX)) {
|
||||
final StructureLoader sharedCl = context.getSharedLoader();
|
||||
final Class<?> cl = sharedCl.loadClass(name);
|
||||
if (! structureAccessAdded) {
|
||||
if (cl.getClassLoader() == sharedCl) {
|
||||
structureAccessAdded = true;
|
||||
final Module structModule = sharedCl.getModule();
|
||||
addModuleExports(structModule, SCRIPTS_PKG, scriptModule);
|
||||
addReadsModule(scriptModule, structModule);
|
||||
}
|
||||
final Class<?> cl = super.loadClass(name, resolve);
|
||||
if (!structureAccessAdded) {
|
||||
final StructureLoader structLoader = context.getStructLoader();
|
||||
if (cl.getClassLoader() == structLoader) {
|
||||
structureAccessAdded = true;
|
||||
structLoader.addModuleExport(scriptModule);
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
return super.loadClass(name, resolve);
|
||||
return cl;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
final ClassLoader appLoader = context.getAppLoader();
|
||||
|
||||
/*
|
||||
* If the appLoader is null, don't bother side-delegating to it!
|
||||
* Bootloader has been already attempted via parent loader
|
||||
* delegation from the "loadClass" method.
|
||||
*
|
||||
* Also, make sure that we don't delegate to the app loader
|
||||
* for nashorn's own classes or nashorn generated classes!
|
||||
*/
|
||||
if (appLoader == null || name.startsWith(NASHORN_PKG_PREFIX)) {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* This split-delegation is used so that caller loader
|
||||
* based resolutions of classes would work. For example,
|
||||
* java.sql.DriverManager uses caller's class loader to
|
||||
* get Driver instances. Without this split-delegation
|
||||
* a script class evaluating DriverManager.getDrivers()
|
||||
* will not get back any JDBC driver!
|
||||
*/
|
||||
return appLoader.loadClass(name);
|
||||
}
|
||||
|
||||
// package-private and private stuff below this point
|
||||
|
||||
@ -30,6 +30,7 @@ import static jdk.nashorn.internal.codegen.Compiler.binaryName;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_DUAL_FIELD_PREFIX;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_SINGLE_FIELD_PREFIX;
|
||||
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.reflect.Module;
|
||||
import java.security.ProtectionDomain;
|
||||
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
|
||||
@ -50,17 +51,26 @@ final class StructureLoader extends NashornLoader {
|
||||
super(parent);
|
||||
|
||||
// new structures module, it's exports, read edges
|
||||
structuresModule = defineModule("jdk.scripting.nashorn.structures", this);
|
||||
addModuleExports(structuresModule, SCRIPTS_PKG, nashornModule);
|
||||
addReadsModule(structuresModule, nashornModule);
|
||||
addReadsModule(structuresModule, Object.class.getModule());
|
||||
structuresModule = createModule("jdk.scripting.nashorn.structures");
|
||||
|
||||
// specific exports from nashorn to the structures module
|
||||
nashornModule.addExports(SCRIPTS_PKG, structuresModule);
|
||||
nashornModule.addExports(RUNTIME_PKG, structuresModule);
|
||||
NASHORN_MODULE.addExports(SCRIPTS_PKG, structuresModule);
|
||||
NASHORN_MODULE.addExports(RUNTIME_PKG, structuresModule);
|
||||
|
||||
// nashorn has to read fields from classes of the new module
|
||||
nashornModule.addReads(structuresModule);
|
||||
NASHORN_MODULE.addReads(structuresModule);
|
||||
}
|
||||
|
||||
private Module createModule(final String moduleName) {
|
||||
final ModuleDescriptor descriptor
|
||||
= new ModuleDescriptor.Builder(moduleName)
|
||||
.requires(NASHORN_MODULE.getName())
|
||||
.conceals(SCRIPTS_PKG)
|
||||
.build();
|
||||
|
||||
final Module mod = Context.createModuleTrusted(descriptor, this);
|
||||
loadModuleManipulator();
|
||||
return mod;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +100,7 @@ final class StructureLoader extends NashornLoader {
|
||||
return isDualFieldStructure(name) || isSingleFieldStructure(name);
|
||||
}
|
||||
|
||||
protected Module getModule() {
|
||||
Module getModule() {
|
||||
return structuresModule;
|
||||
}
|
||||
|
||||
|
||||
@ -31,12 +31,24 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_VARARGS;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.AALOAD;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ARRAYLENGTH;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.D2F;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.GOTO;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.I2B;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.I2S;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.POP;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.PUTSTATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
|
||||
@ -62,6 +74,12 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.FieldVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
@ -69,6 +87,7 @@ import jdk.internal.org.objectweb.asm.Type;
|
||||
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import jdk.nashorn.api.scripting.ScriptUtils;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
|
||||
@ -136,6 +155,9 @@ import jdk.internal.reflect.CallerSensitive;
|
||||
* implemented securely.
|
||||
*/
|
||||
final class JavaAdapterBytecodeGenerator {
|
||||
private static final Module NASHORN_MODULE = Context.class.getModule();
|
||||
private static final Module JAVA_BASE_MODULE = Object.class.getModule();
|
||||
|
||||
// Field names in adapters
|
||||
private static final String GLOBAL_FIELD_NAME = "global";
|
||||
private static final String DELEGATE_FIELD_NAME = "delegate";
|
||||
@ -211,6 +233,17 @@ final class JavaAdapterBytecodeGenerator {
|
||||
private static final String FINALIZER_DELEGATE_NAME = "$$nashornFinalizerDelegate";
|
||||
private static final String FINALIZER_DELEGATE_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE);
|
||||
|
||||
// adapter class may need module read-edges from other modules.
|
||||
// We generate a class to add those required module read-edges.
|
||||
// This is the name of the module read edge adder class.
|
||||
static final String MODULES_READ_ADDER_INTERNAL = ADAPTER_PACKAGE_INTERNAL + "$ModulesReadAdder";
|
||||
static final String MODULES_READ_ADDER = MODULES_READ_ADDER_INTERNAL.replace('/', '.');
|
||||
// module add read method
|
||||
static final String MODULES_ADD_READS = "addReads";
|
||||
|
||||
// .class bytes of module add reader class. Lazily generated and cached.
|
||||
private static byte[] MODULES_READ_ADDER_BYRES;
|
||||
|
||||
/**
|
||||
* Collection of methods we never override: Object.clone(), Object.finalize().
|
||||
*/
|
||||
@ -307,6 +340,21 @@ final class JavaAdapterBytecodeGenerator {
|
||||
return autoConvertibleFromFunction;
|
||||
}
|
||||
|
||||
static synchronized byte[] getModulesAddReadsBytes() {
|
||||
if (MODULES_READ_ADDER_BYRES == null) {
|
||||
// lazily generate module read edge adder class
|
||||
MODULES_READ_ADDER_BYRES = generateModulesReadAdderClass();
|
||||
}
|
||||
|
||||
return MODULES_READ_ADDER_BYRES;
|
||||
}
|
||||
|
||||
private void addAccessedModule(Module m) {
|
||||
if (m != null && m != JAVA_BASE_MODULE && m != NASHORN_MODULE) {
|
||||
accessedModules.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getGeneratedClassName(final Class<?> superType, final List<Class<?>> interfaces) {
|
||||
// The class we use to primarily name our adapter is either the superclass, or if it is Object (meaning we're
|
||||
// just implementing interfaces or extending Object), then the first implemented interface or Object.
|
||||
@ -1086,10 +1134,7 @@ final class JavaAdapterBytecodeGenerator {
|
||||
*/
|
||||
private void gatherMethods(final Class<?> type) throws AdaptationException {
|
||||
if (Modifier.isPublic(type.getModifiers())) {
|
||||
final Module module = type.getModule();
|
||||
if (module != null) {
|
||||
accessedModules.add(module);
|
||||
}
|
||||
addAccessedModule(type.getModule());
|
||||
|
||||
final Method[] typeMethods = type.isInterface() ? type.getMethods() : type.getDeclaredMethods();
|
||||
|
||||
@ -1117,16 +1162,12 @@ final class JavaAdapterBytecodeGenerator {
|
||||
|
||||
for (final Class<?> pt : typeMethod.getParameterTypes()) {
|
||||
if (pt.isPrimitive()) continue;
|
||||
final Module ptMod = pt.getModule();
|
||||
if (ptMod != null) {
|
||||
accessedModules.add(ptMod);
|
||||
}
|
||||
addAccessedModule(pt.getModule());
|
||||
}
|
||||
|
||||
final Class<?> rt = typeMethod.getReturnType();
|
||||
if (!rt.isPrimitive()) {
|
||||
final Module rtMod = rt.getModule();
|
||||
if (rtMod != null) accessedModules.add(rtMod);
|
||||
addAccessedModule(rt.getModule());
|
||||
}
|
||||
|
||||
final MethodInfo mi = new MethodInfo(typeMethod);
|
||||
@ -1211,7 +1252,95 @@ final class JavaAdapterBytecodeGenerator {
|
||||
return e.isAnnotationPresent(CallerSensitive.class);
|
||||
}
|
||||
|
||||
private static final Call lookupServiceMethod(final String name, final Class<?> rtype, final Class<?>... ptypes) {
|
||||
private static Call lookupServiceMethod(final String name, final Class<?> rtype, final Class<?>... ptypes) {
|
||||
return staticCallNoLookup(JavaAdapterServices.class, name, rtype, ptypes);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a class that adds module read edges from adapter module to the
|
||||
* modules of the reference types used by the generated adapter class.
|
||||
*/
|
||||
private static byte[] generateModulesReadAdderClass() {
|
||||
final ClassWriter cw = new ClassWriter(0);
|
||||
MethodVisitor mv;
|
||||
|
||||
// make the class package private
|
||||
cw.visit(Opcodes.V1_7, ACC_SUPER | ACC_FINAL, MODULES_READ_ADDER_INTERNAL,
|
||||
null, "java/lang/Object", null);
|
||||
|
||||
// private static final Module MY_MODULE;
|
||||
{
|
||||
FieldVisitor fv = cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC,
|
||||
"MY_MODULE", "Ljava/lang/reflect/Module;", null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
|
||||
/*
|
||||
* private static void addReads(Module[] modules) {
|
||||
* for (Module m : mods) {
|
||||
* MY_MODULE.addRead(m);
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
{
|
||||
mv = cw.visitMethod(ACC_PRIVATE | ACC_STATIC,
|
||||
MODULES_ADD_READS,
|
||||
"([Ljava/lang/reflect/Module;)V", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ASTORE, 1);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitInsn(ARRAYLENGTH);
|
||||
mv.visitVarInsn(ISTORE, 2);
|
||||
mv.visitInsn(ICONST_0);
|
||||
mv.visitVarInsn(ISTORE, 3);
|
||||
Label l0 = new Label();
|
||||
mv.visitLabel(l0);
|
||||
mv.visitFrame(Opcodes.F_APPEND, 3,
|
||||
new Object[]{"[Ljava/lang/reflect/Module;",
|
||||
Opcodes.INTEGER, Opcodes.INTEGER}, 0, null);
|
||||
mv.visitVarInsn(ILOAD, 3);
|
||||
mv.visitVarInsn(ILOAD, 2);
|
||||
Label l1 = new Label();
|
||||
mv.visitJumpInsn(IF_ICMPGE, l1);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ILOAD, 3);
|
||||
mv.visitInsn(AALOAD);
|
||||
mv.visitVarInsn(ASTORE, 4);
|
||||
mv.visitFieldInsn(GETSTATIC, MODULES_READ_ADDER_INTERNAL,
|
||||
"MY_MODULE", "Ljava/lang/reflect/Module;");
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Module",
|
||||
"addReads", "(Ljava/lang/reflect/Module;)Ljava/lang/reflect/Module;", false);
|
||||
mv.visitInsn(POP);
|
||||
mv.visitIincInsn(3, 1);
|
||||
mv.visitJumpInsn(GOTO, l0);
|
||||
mv.visitLabel(l1);
|
||||
mv.visitFrame(Opcodes.F_CHOP, 3, null, 0, null);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 5);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
/*
|
||||
* static {
|
||||
* MY_MODULE = ThisClass.class.getModule();
|
||||
* }
|
||||
*/
|
||||
{
|
||||
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitLdcInsn(Type.getType("L" + MODULES_READ_ADDER_INTERNAL + ";"));
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class",
|
||||
"getModule", "()Ljava/lang/reflect/Module;", false);
|
||||
mv.visitFieldInsn(PUTSTATIC, MODULES_READ_ADDER_INTERNAL,
|
||||
"MY_MODULE", "Ljava/lang/reflect/Module;");
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(1, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
cw.visitEnd();
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
|
||||
package jdk.nashorn.internal.runtime.linker;
|
||||
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Module;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
@ -42,7 +45,6 @@ import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.internal.module.Modules;
|
||||
|
||||
/**
|
||||
* This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class.
|
||||
@ -52,14 +54,12 @@ import jdk.internal.module.Modules;
|
||||
* class are normally created by {@code JavaAdapterBytecodeGenerator}.
|
||||
*/
|
||||
final class JavaAdapterClassLoader {
|
||||
private static final Module nashornModule = JavaAdapterClassLoader.class.getModule();
|
||||
private static final Set<String> adapterPkgs = new HashSet<>();
|
||||
static {
|
||||
adapterPkgs.add(JavaAdapterBytecodeGenerator.ADAPTER_PACKAGE);
|
||||
}
|
||||
private static final Module NASHORN_MODULE = Context.class.getModule();
|
||||
|
||||
private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
|
||||
private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT);
|
||||
private static final AccessControlContext CREATE_MODULE_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_CREATE_MODULE);
|
||||
|
||||
private static final Collection<String> VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>(
|
||||
Arrays.asList(JavaAdapterServices.class.getName(), ScriptObject.class.getName(), ScriptFunction.class.getName(), JSType.class.getName())));
|
||||
|
||||
@ -93,12 +93,19 @@ final class JavaAdapterClassLoader {
|
||||
}, CREATE_LOADER_ACC_CTXT);
|
||||
}
|
||||
|
||||
private static void addExports(final Module from, final String pkg, final Module to) {
|
||||
if (to == null) {
|
||||
Modules.addExportsToAll(from, pkg);
|
||||
} else {
|
||||
Modules.addExports(from, pkg, to);
|
||||
}
|
||||
private static Module createAdapterModule(final ClassLoader loader) {
|
||||
final ModuleDescriptor descriptor =
|
||||
new ModuleDescriptor.Builder("jdk.scripting.nashorn.javaadapters")
|
||||
.requires(NASHORN_MODULE.getName())
|
||||
.exports(JavaAdapterBytecodeGenerator.ADAPTER_PACKAGE)
|
||||
.build();
|
||||
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Module>() {
|
||||
@Override
|
||||
public Module run() {
|
||||
return Context.createModule(descriptor, loader);
|
||||
}
|
||||
}, CREATE_MODULE_ACC_CTXT);
|
||||
}
|
||||
|
||||
// Note that the adapter class is created in the protection domain of the class/interface being
|
||||
@ -113,23 +120,44 @@ final class JavaAdapterClassLoader {
|
||||
private final ClassLoader myLoader = getClass().getClassLoader();
|
||||
|
||||
// new adapter module
|
||||
private final Module adapterModule = Modules.defineModule(this, "jdk.scripting.nashorn.javaadapters", adapterPkgs);
|
||||
private final Module adapterModule = createAdapterModule(this);
|
||||
|
||||
{
|
||||
// new adapter module exports and read-edges
|
||||
addExports(adapterModule, JavaAdapterBytecodeGenerator.ADAPTER_PACKAGE, null);
|
||||
Modules.addReads(adapterModule, nashornModule);
|
||||
Modules.addReads(adapterModule, Object.class.getModule());
|
||||
for (Module mod : accessedModules) {
|
||||
Modules.addReads(adapterModule, mod);
|
||||
// new adapter module read-edges
|
||||
if (!accessedModules.isEmpty()) {
|
||||
|
||||
// There are modules accessed from this adapter. We need to add module-read
|
||||
// edges to those from the adapter module. We do this by generating a
|
||||
// package-private class, loading it with this adapter class loader and
|
||||
// then calling a private static method on it.
|
||||
final byte[] buf = JavaAdapterBytecodeGenerator.getModulesAddReadsBytes();
|
||||
final Class<?> addReader = defineClass(
|
||||
JavaAdapterBytecodeGenerator.MODULES_READ_ADDER, buf, 0, buf.length);
|
||||
final PrivilegedAction<Method> pa = () -> {
|
||||
try {
|
||||
final Method m = addReader.getDeclaredMethod(
|
||||
JavaAdapterBytecodeGenerator.MODULES_ADD_READS, Module[].class);
|
||||
m.setAccessible(true);
|
||||
return m;
|
||||
} catch (final NoSuchMethodException | SecurityException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
};
|
||||
final Method addReads = AccessController.doPrivileged(pa);
|
||||
try {
|
||||
addReads.invoke(null, (Object)accessedModules.toArray(new Module[0]));
|
||||
} catch (final IllegalAccessException | IllegalArgumentException |
|
||||
InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// specific exports from nashorn to the new adapter module
|
||||
nashornModule.addExports("jdk.nashorn.internal.runtime", adapterModule);
|
||||
nashornModule.addExports("jdk.nashorn.internal.runtime.linker", adapterModule);
|
||||
NASHORN_MODULE.addExports("jdk.nashorn.internal.runtime", adapterModule);
|
||||
NASHORN_MODULE.addExports("jdk.nashorn.internal.runtime.linker", adapterModule);
|
||||
|
||||
// nashorn should be be able to read methods of classes loaded in adapter module
|
||||
nashornModule.addReads(adapterModule);
|
||||
NASHORN_MODULE.addReads(adapterModule);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -27,7 +27,6 @@ package jdk.nashorn.internal.runtime.linker;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Modifier;
|
||||
import jdk.internal.module.Modules;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.NamedOperation;
|
||||
import jdk.dynalink.StandardOperation;
|
||||
@ -93,7 +92,6 @@ final class NashornStaticClassLinker implements TypeBasedGuardingDynamicLinker {
|
||||
NashornCallSiteDescriptor.getLookupInternal(request.getCallSiteDescriptor());
|
||||
|
||||
args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null, lookup);
|
||||
Modules.addReads(lookup.lookupClass().getModule(), ((StaticClass)args[0]).getRepresentedClass().getModule());
|
||||
final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args);
|
||||
final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass);
|
||||
// Finally, modify the guard to test for the original abstract class.
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.nashorn.internal.scripts;
|
||||
|
||||
import java.lang.reflect.Module;
|
||||
import jdk.nashorn.api.scripting.JSObject;
|
||||
|
||||
/**
|
||||
* Nashorn's StructureLoader and ScriptLoader instances load
|
||||
* this class in the respective dynamic modules created. This
|
||||
* class is never loaded by Nashorn's own class loader. The
|
||||
* .class bytes of this class are loaded as resource by the
|
||||
* {@link jdk.nashorn.internal.runtime.NashornLoader} class. This class
|
||||
* exists in this package because nashorn structures and scripts
|
||||
* modules use this package name for the only exported package
|
||||
* from those modules.
|
||||
*
|
||||
* Note that this class may be dynamically generated at runtime.
|
||||
* But, this java source is used for ease of reading.
|
||||
*/
|
||||
final class ModuleGraphManipulator {
|
||||
private ModuleGraphManipulator() {}
|
||||
|
||||
private static final Module MY_MODULE;
|
||||
private static final String MY_PKG_NAME;
|
||||
|
||||
static {
|
||||
final Class<?> myClass = ModuleGraphManipulator.class;
|
||||
MY_MODULE = myClass.getModule();
|
||||
final String myName = myClass.getName();
|
||||
MY_PKG_NAME = myName.substring(0, myName.lastIndexOf('.'));
|
||||
|
||||
// nashorn's module is the module of the class loader of current class
|
||||
final Module nashornModule = myClass.getClassLoader().getClass().getModule();
|
||||
|
||||
// Make sure this class was not loaded by Nashorn's own loader!
|
||||
if (MY_MODULE == nashornModule) {
|
||||
throw new IllegalStateException(myClass + " loaded by wrong loader!");
|
||||
}
|
||||
|
||||
// From this module add a qualified export to nashorn module
|
||||
MY_MODULE.addExports(MY_PKG_NAME, nashornModule);
|
||||
}
|
||||
|
||||
// The following method is reflectively invoked from Nashorn
|
||||
// to add required module export edges. Because this package
|
||||
// itself is qualified exported only to nashorn and this
|
||||
// method is private, unsafe calls are not possible.
|
||||
|
||||
private static void addExport(final Module otherMod) {
|
||||
MY_MODULE.addExports(MY_PKG_NAME, otherMod);
|
||||
}
|
||||
}
|
||||
92
nashorn/test/script/basic/JDK-8158467.js
Normal file
92
nashorn/test/script/basic/JDK-8158467.js
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8158467: AccessControlException is thrown on public Java class access if "script app loader" is set to null
|
||||
*
|
||||
* @option -scripting
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var Factory = Java.type("jdk.nashorn.api.scripting.NashornScriptEngineFactory");
|
||||
var fac = new Factory();
|
||||
|
||||
// This script has to be given RuntimePermission("nashorn.setConfig")
|
||||
var e = fac["getScriptEngine(java.lang.ClassLoader)"](null);
|
||||
|
||||
print(e.eval("java.lang.System"));
|
||||
print(e.eval("({ foo: 42})").foo);
|
||||
print((e.eval("function(x) x*x"))(31));
|
||||
|
||||
e.put("output", print);
|
||||
var runnable = e.eval(<<EOF
|
||||
new java.lang.Runnable() {
|
||||
run: function() {
|
||||
output("hello Runnable");
|
||||
}
|
||||
}
|
||||
EOF);
|
||||
|
||||
runnable.run();
|
||||
|
||||
var obj = e.eval(<<EOF
|
||||
new (Java.extend(Java.type("java.lang.Object"))) {
|
||||
hashCode: function() 33,
|
||||
toString: function() "I'm object"
|
||||
}
|
||||
EOF);
|
||||
|
||||
print(obj.hashCode());
|
||||
print(obj.toString());
|
||||
|
||||
// should throw SecurityException!
|
||||
try {
|
||||
e.eval("Packages.jdk.internal");
|
||||
} catch (ex) {
|
||||
print(ex);
|
||||
}
|
||||
|
||||
// should throw SecurityException!
|
||||
try {
|
||||
e.eval("Java.type('jdk.internal.misc.Unsafe')");
|
||||
} catch (ex) {
|
||||
print(ex);
|
||||
}
|
||||
|
||||
// should throw SecurityException!
|
||||
try {
|
||||
e.eval("Java.type('jdk.nashorn.internal.Context')");
|
||||
} catch (ex) {
|
||||
print(ex);
|
||||
}
|
||||
|
||||
// should throw ClassNotFoundException as null is script
|
||||
// "app loader" [and not platform loader which loads nashorn]
|
||||
e.eval(<<EOF
|
||||
try {
|
||||
Java.type('jdk.nashorn.api.scripting.JSObject');
|
||||
} catch (ex) {
|
||||
output(ex);
|
||||
}
|
||||
EOF);
|
||||
10
nashorn/test/script/basic/JDK-8158467.js.EXPECTED
Normal file
10
nashorn/test/script/basic/JDK-8158467.js.EXPECTED
Normal file
@ -0,0 +1,10 @@
|
||||
[JavaClass java.lang.System]
|
||||
42
|
||||
961
|
||||
hello Runnable
|
||||
33
|
||||
I'm object
|
||||
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.jdk.internal")
|
||||
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.jdk.internal.misc")
|
||||
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.jdk.nashorn.internal")
|
||||
java.lang.ClassNotFoundException: jdk.nashorn.api.scripting.JSObject
|
||||
Loading…
x
Reference in New Issue
Block a user