From 4bc1c3af5304943dc3a51001a31cc6e10921ca6d Mon Sep 17 00:00:00 2001 From: Dalibor Topic Date: Mon, 30 May 2016 16:41:57 +0200 Subject: [PATCH 1/5] 8154469: Update FSF address Updated Free Software Foundation's mailing address in LICENSE Reviewed-by: rriggs, shade --- nashorn/LICENSE | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nashorn/LICENSE b/nashorn/LICENSE index b40a0f457d7..8b400c7ab81 100644 --- a/nashorn/LICENSE +++ b/nashorn/LICENSE @@ -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. From 4489e7f18c6d90003f4a8bc69457573e2763f762 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Tue, 31 May 2016 13:04:26 +0530 Subject: [PATCH 2/5] 8158131: Nashorn should not use jdk.internal.module.Modules API Reviewed-by: hannesw, mhaupt, alanb --- .../jdk/nashorn/internal/runtime/Context.java | 94 ++++++++++- .../internal/runtime/NashornLoader.java | 69 +++++--- .../internal/runtime/ScriptLoader.java | 43 +++-- .../internal/runtime/StructureLoader.java | 26 ++- .../linker/JavaAdapterBytecodeGenerator.java | 151 ++++++++++++++++-- .../linker/JavaAdapterClassLoader.java | 72 ++++++--- .../linker/NashornStaticClassLinker.java | 2 - .../scripts/ModuleGraphManipulator.java | 76 +++++++++ 8 files changed, 452 insertions(+), 81 deletions(-) create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java index 94f224e2b22..506cb5afbd9 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java @@ -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(); @@ -486,7 +501,6 @@ 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; private static final ConcurrentMap> structureClasses = new ConcurrentHashMap<>(); @@ -508,8 +522,10 @@ 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 { + final ClassLoader myLoader = Context.class.getClassLoader(); sharedLoader = AccessController.doPrivileged(new PrivilegedAction() { @Override public StructureLoader run() { @@ -791,7 +807,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) { @@ -1281,6 +1297,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(""); + throw new UncheckedIOException(ioe); + }); + + final ModuleFinder finder = new ModuleFinder() { + @Override + public Optional find(String name) { + if (name.equals(mn)) { + return Optional.of(mref); + } else { + return Optional.empty(); + } + } + @Override + public Set findAll() { + return Set.of(mref); + } + }; + + final Configuration cf = parent.configuration() + .resolveRequires(finder, ModuleFinder.of(), Set.of(mn)); + + final PrivilegedAction 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); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java index 78256cc7185..b96ec5a8851 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java @@ -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 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 runs! + try { + Class.forName(MODULE_MANIPULATOR_NAME, true, this); + } catch (final Exception ex) { + throw new RuntimeException(ex); + } + final PrivilegedAction 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 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); + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java index 79028705238..645063e4611 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java @@ -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; @@ -52,35 +53,43 @@ final class ScriptLoader extends NashornLoader { 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.getSharedLoader().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); - } + if (!structureAccessAdded && cl.getClassLoader() == sharedCl) { + structureAccessAdded = true; + sharedCl.addModuleExport(scriptModule); } return cl; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java index b179c257be4..d9950e7be3f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java @@ -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; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java index 8dd697f6913..e354abb684f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java @@ -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> 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, "", "()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(); + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java index 5498bed1b86..445e2bb276b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java @@ -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 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 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() { + @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 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 diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java index 60c44c68449..99ceb73e087 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java @@ -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. diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java new file mode 100644 index 00000000000..cc9e76efcfe --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java @@ -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); + } +} From 5f496062257e85156ac2e4467f742f105c5463d8 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Tue, 31 May 2016 21:12:34 +0530 Subject: [PATCH 3/5] 8158250: nashorn ant javadoc targets are broken Reviewed-by: hannesw, mhaupt --- nashorn/make/build.xml | 40 +++++++------------ nashorn/make/project.properties | 5 ++- .../jdk/nashorn/internal/ir/Module.java | 4 +- .../jdk/nashorn/internal/parser/Parser.java | 3 ++ 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 9aced2f767a..bbc6f7cebd5 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -258,31 +258,13 @@ - + - - - - - - - - - - - - - - - - - - + + @@ -295,10 +277,13 @@ - - + + + + @@ -310,9 +295,12 @@ - + + + @@ -322,6 +310,8 @@ + + @@ -595,7 +585,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - + diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties index eb406cacc7a..43f4394495e 100644 --- a/nashorn/make/project.properties +++ b/nashorn/make/project.properties @@ -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 diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java index 28279abbfc6..0b144cc3288 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java @@ -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 es6 modules */ 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 es6 modules */ public static final class ImportEntry { private final String moduleRequest; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java index c8936ef94bc..ec17f387cb6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java @@ -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 From 3c9941bd80c8337a4776d3f5a6b7713543fbfa9d Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Wed, 1 Jun 2016 15:17:37 +0530 Subject: [PATCH 4/5] 8158338: Nashorn's ScriptLoader split delegation has to be adjusted Reviewed-by: lagergren, hannesw --- .../jdk/nashorn/internal/runtime/Context.java | 20 +++++--- .../internal/runtime/ScriptLoader.java | 49 ++++++++++++++----- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java index 506cb5afbd9..71c6d7927f9 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java @@ -486,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; @@ -501,12 +506,13 @@ public final class Context { /** Optional class filter to use for Java classes. Can be null. */ private final ClassFilter classFilter; - private static final StructureLoader sharedLoader; + /** Process-wide singleton structure loader */ + private static final StructureLoader theStructLoader; private static final ConcurrentMap> structureClasses = new ConcurrentHashMap<>(); /*package-private*/ @SuppressWarnings("static-method") - StructureLoader getSharedLoader() { - return sharedLoader; + StructureLoader getStructLoader() { + return theStructLoader; } private static AccessControlContext createNoPermAccCtxt() { @@ -526,7 +532,7 @@ public final class Context { static { final ClassLoader myLoader = Context.class.getClassLoader(); - sharedLoader = AccessController.doPrivileged(new PrivilegedAction() { + theStructLoader = AccessController.doPrivileged(new PrivilegedAction() { @Override public StructureLoader run() { return new StructureLoader(myLoader); @@ -1038,7 +1044,7 @@ public final class Context { } return (Class)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); } @@ -1191,7 +1197,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)); } } } @@ -1551,7 +1557,7 @@ public final class Context { new PrivilegedAction() { @Override public ScriptLoader run() { - return new ScriptLoader(appLoader, Context.this); + return new ScriptLoader(Context.this); } }, CREATE_LOADER_ACC_CTXT); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java index 645063e4611..d3602c13d1d 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java @@ -38,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; @@ -48,8 +48,8 @@ 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 @@ -67,7 +67,7 @@ final class ScriptLoader extends NashornLoader { } private Module createModule(final String moduleName) { - final Module structMod = context.getSharedLoader().getModule(); + final Module structMod = context.getStructLoader().getModule(); final ModuleDescriptor descriptor = new ModuleDescriptor.Builder(moduleName) .requires(NASHORN_MODULE.getName()) @@ -80,20 +80,45 @@ final class ScriptLoader extends NashornLoader { 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 && cl.getClassLoader() == sharedCl) { + final Class cl = super.loadClass(name, resolve); + if (!structureAccessAdded) { + final StructureLoader structLoader = context.getStructLoader(); + if (cl.getClassLoader() == structLoader) { structureAccessAdded = true; - sharedCl.addModuleExport(scriptModule); + 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 From 2c1f125385a9332471cee40e90d78d2cfb42c2a4 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Thu, 2 Jun 2016 14:56:20 +0530 Subject: [PATCH 5/5] 8158467: AccessControlException is thrown on public Java class access if "script app loader" is set to null Reviewed-by: mhaupt, hannesw --- nashorn/make/build.xml | 4 + .../jdk/nashorn/internal/runtime/Context.java | 12 ++- nashorn/test/script/basic/JDK-8158467.js | 92 +++++++++++++++++++ .../test/script/basic/JDK-8158467.js.EXPECTED | 10 ++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 nashorn/test/script/basic/JDK-8158467.js create mode 100644 nashorn/test/script/basic/JDK-8158467.js.EXPECTED diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index bbc6f7cebd5..0ece37f415f 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -492,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"; +}; + \/ diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java index 71c6d7927f9..9d51ed4a093 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java @@ -1166,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); + } + } } /** diff --git a/nashorn/test/script/basic/JDK-8158467.js b/nashorn/test/script/basic/JDK-8158467.js new file mode 100644 index 00000000000..c67107768d4 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8158467.js @@ -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(<