From 27a15adb2687a96d252e43a7e1332e2c1cc2a8f0 Mon Sep 17 00:00:00 2001
From: Attila Szegedi
Date: Sun, 5 Jan 2025 18:59:55 +0100
Subject: [PATCH] No longer use SecureClassLoader, CodeSource, Permission, and
ProtectionDomain
---
.../nashorn/internal/objects/NativeJava.java | 18 +--
.../nashorn/internal/runtime/Context.java | 35 +++---
.../internal/runtime/NashornLoader.java | 42 +------
.../internal/runtime/ScriptLoader.java | 10 +-
.../internal/runtime/StructureLoader.java | 3 +-
.../linker/JavaAdapterBytecodeGenerator.java | 9 +-
.../linker/JavaAdapterClassLoader.java | 20 ++--
.../runtime/linker/JavaAdapterFactory.java | 108 +++++-------------
.../linker/NashornStaticClassLinker.java | 7 +-
9 files changed, 68 insertions(+), 184 deletions(-)
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/objects/NativeJava.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/objects/NativeJava.java
index d2880695..15881c59 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/objects/NativeJava.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/objects/NativeJava.java
@@ -28,7 +28,6 @@
import static org.openjdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static org.openjdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import java.lang.invoke.MethodHandles;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
@@ -592,8 +591,8 @@ private static Class> arrayType(final String typeName) throws ClassNotFoundExc
*
* We can see several important concepts in the above example:
*
- * - Every specified list of Java types will have one extender subclass in Nashorn per caller protection domain -
- * repeated invocations of {@code extend} for the same list of types for scripts same protection domain will yield
+ *
- Every specified list of Java types will have one extender subclass in Nashorn -
+ * repeated invocations of {@code extend} for the same list of types will yield
* the same extender type. It's a generic adapter that delegates to whatever JavaScript functions its implementation
* object has on a per-instance basis.
* - If the Java method is overloaded (as in the above example {@code List.add()}), then your JavaScript adapter
@@ -675,18 +674,7 @@ public static Object extend(final Object self, final Object... types) {
} catch(final ClassCastException e) {
throw typeError("extend.expects.java.types");
}
- // Note that while the public API documentation claims self is not used, we actually use it.
- // ScriptFunction.findCallMethod will bind the lookup object into it, and we can then use that lookup when
- // requesting the adapter class. Note that if Java.extend is invoked with no lookup object, it'll pass the
- // public lookup which'll result in generation of a no-permissions adapter. A typical situation this can happen
- // is when the extend function is bound.
- final MethodHandles.Lookup lookup;
- if(self instanceof MethodHandles.Lookup) {
- lookup = (MethodHandles.Lookup)self;
- } else {
- lookup = MethodHandles.publicLookup();
- }
- return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides, lookup);
+ return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides);
}
/**
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java
index 2d3ab1d5..4e8c41bc 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/Context.java
@@ -56,8 +56,6 @@
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.security.CodeSigner;
-import java.security.CodeSource;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -162,11 +160,9 @@ static long getAnonymousInstalledScriptCount() {
*/
private abstract static class ContextCodeInstaller implements CodeInstaller {
final Context context;
- final CodeSource codeSource;
- ContextCodeInstaller(final Context context, final CodeSource codeSource) {
+ ContextCodeInstaller(final Context context) {
this.context = context;
- this.codeSource = codeSource;
}
@Override
@@ -223,7 +219,7 @@ public StoredScript loadScript(final Source source, final String functionKey) {
public boolean isCompatibleWith(final CodeInstaller other) {
if (other instanceof ContextCodeInstaller) {
final ContextCodeInstaller cci = (ContextCodeInstaller)other;
- return cci.context == context && cci.codeSource == codeSource;
+ return cci.context == context;
}
return false;
}
@@ -239,8 +235,8 @@ private static class NamedContextCodeInstaller extends ContextCodeInstaller {
private final static int MAX_USAGES = 10;
private final static int MAX_BYTES_DEFINED = 200_000;
- private NamedContextCodeInstaller(final Context context, final CodeSource codeSource, final ScriptLoader loader) {
- super(context, codeSource);
+ private NamedContextCodeInstaller(final Context context, final ScriptLoader loader) {
+ super(context);
this.loader = loader;
}
@@ -249,7 +245,7 @@ public Class> install(final String className, final byte[] bytecode) {
usageCount++;
bytesDefined += bytecode.length;
NAMED_INSTALLED_SCRIPT_COUNT.increment();
- return loader.installClass(Compiler.binaryName(className), bytecode, codeSource);
+ return loader.installClass(Compiler.binaryName(className), bytecode);
}
@Override
@@ -258,7 +254,7 @@ public CodeInstaller getOnDemandCompilationInstaller() {
if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
return this;
}
- return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
+ return new NamedContextCodeInstaller(context, context.createNewLoader());
}
@Override
@@ -269,7 +265,7 @@ public CodeInstaller getMultiClassCodeInstaller() {
}
}
- private final WeakValueCache> anonymousHostClasses = new WeakValueCache<>();
+ private final WeakValueCache> anonymousHostClasses = new WeakValueCache<>();
private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller {
private static final MethodHandle DEFINE_ANONYMOUS_CLASS = getDefineAnonymousClass();
@@ -292,8 +288,8 @@ private static MethodHandle getDefineAnonymousClass() {
}
}
- private AnonymousContextCodeInstaller(final Context context, final CodeSource codeSource, final Class> hostClass) {
- super(context, codeSource);
+ private AnonymousContextCodeInstaller(final Context context, final Class> hostClass) {
+ super(context);
this.hostClass = hostClass;
}
@@ -320,7 +316,7 @@ public CodeInstaller getMultiClassCodeInstaller() {
// This code loader can not be used to install multiple classes that reference each other, as they
// would have no resolvable names. Therefore, in such situation we must revert to an installer that
// produces named classes.
- return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
+ return new NamedContextCodeInstaller(context, context.createNewLoader());
}
private static byte[] getAnonymousHostClassBytes() {
@@ -1335,23 +1331,22 @@ private synchronized Class> compile(final Source source, final ErrorManager er
return null;
}
- final URL url = source.getURL();
- final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
+ final URL url = source.getURL();
final CodeInstaller installer;
if (env._persistent_cache || !env._lazy_compilation || !env.useAnonymousClasses(source.getLength(), () -> AnonymousContextCodeInstaller.initFailure) ) {
// Persistent code cache, eager compilation, or inability to use Unsafe.defineAnonymousClass (typically, JDK 17+)
// preclude use of VM anonymous classes
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
- installer = new NamedContextCodeInstaller(this, cs, loader);
+ installer = new NamedContextCodeInstaller(this, loader);
} else {
- installer = new AnonymousContextCodeInstaller(this, cs,
- anonymousHostClasses.getOrCreate(cs, (key) ->
+ installer = new AnonymousContextCodeInstaller(this,
+ anonymousHostClasses.getOrCreate(url, key ->
createNewLoader().installClass(
// NOTE: we're defining these constants in AnonymousContextCodeInstaller so they are not
// initialized if we don't use AnonymousContextCodeInstaller. As this method is only ever
// invoked from AnonymousContextCodeInstaller, this is okay.
AnonymousContextCodeInstaller.ANONYMOUS_HOST_CLASS_NAME,
- AnonymousContextCodeInstaller.ANONYMOUS_HOST_CLASS_BYTES, cs)));
+ AnonymousContextCodeInstaller.ANONYMOUS_HOST_CLASS_BYTES)));
}
if (storedScript == null) {
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/NashornLoader.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/NashornLoader.java
index f5eb22b4..7928b7cf 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/NashornLoader.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/NashornLoader.java
@@ -34,47 +34,20 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
-import java.security.CodeSource;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Permissions;
-import java.security.SecureClassLoader;
import java.util.Arrays;
/**
* Superclass for Nashorn class loader classes.
*/
-abstract class NashornLoader extends SecureClassLoader {
- protected static final String OBJECTS_PKG = "org.openjdk.nashorn.internal.objects";
- protected static final String RUNTIME_PKG = "org.openjdk.nashorn.internal.runtime";
- protected static final String RUNTIME_ARRAYS_PKG = "org.openjdk.nashorn.internal.runtime.arrays";
- protected static final String RUNTIME_LINKER_PKG = "org.openjdk.nashorn.internal.runtime.linker";
- protected static final String SCRIPTS_PKG = "org.openjdk.nashorn.internal.scripts";
+abstract class NashornLoader extends ClassLoader {
+ protected static final String RUNTIME_PKG = "org.openjdk.nashorn.internal.runtime";
+ protected static final String SCRIPTS_PKG = "org.openjdk.nashorn.internal.scripts";
static final Module NASHORN_MODULE = Context.class.getModule();
- private static final Permission[] SCRIPT_PERMISSIONS;
-
private static final String MODULE_MANIPULATOR_NAME = SCRIPTS_PKG + ".ModuleGraphManipulator";
private static final byte[] MODULE_MANIPULATOR_BYTES = readModuleManipulatorBytes();
- static {
- /*
- * Generated classes get access to runtime, runtime.linker, objects, scripts packages.
- * Note that the actual scripts can not access these because Java.type, Packages
- * prevent these restricted packages. And Java reflection and JSR292 access is prevented
- * for scripts. In other words, nashorn generated portions of script classes can access
- * classes in these implementation packages.
- */
- SCRIPT_PERMISSIONS = new Permission[] {
- new RuntimePermission("accessClassInPackage." + RUNTIME_PKG),
- new RuntimePermission("accessClassInPackage." + RUNTIME_LINKER_PKG),
- new RuntimePermission("accessClassInPackage." + OBJECTS_PKG),
- new RuntimePermission("accessClassInPackage." + SCRIPTS_PKG),
- new RuntimePermission("accessClassInPackage." + RUNTIME_ARRAYS_PKG)
- };
- }
-
// addExport Method object on ModuleGraphManipulator
// class loaded by this loader
private Method addModuleExport;
@@ -116,15 +89,6 @@ static boolean isInNamedModule() {
return NASHORN_MODULE.isNamed();
}
- @Override
- protected PermissionCollection getPermissions(final CodeSource codesource) {
- final Permissions permCollection = new Permissions();
- for (final Permission perm : SCRIPT_PERMISSIONS) {
- permCollection.add(perm);
- }
- return permCollection;
- }
-
/**
* Create a secure URL class loader for the given classpath
* @param classPath classpath for the loader to search from
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/ScriptLoader.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/ScriptLoader.java
index 7644c340..26a7802f 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/ScriptLoader.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/ScriptLoader.java
@@ -27,8 +27,6 @@
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Modifier;
-import java.security.CodeSource;
-import java.util.Objects;
import java.util.Set;
/**
@@ -36,6 +34,9 @@
*
*/
final class ScriptLoader extends NashornLoader {
+ private static final String OBJECTS_PKG = "org.openjdk.nashorn.internal.objects";
+ private static final String RUNTIME_ARRAYS_PKG = "org.openjdk.nashorn.internal.runtime.arrays";
+ private static final String RUNTIME_LINKER_PKG = "org.openjdk.nashorn.internal.runtime.linker";
private static final String NASHORN_PKG_PREFIX = "org.openjdk.nashorn.internal.";
private volatile boolean structureAccessAdded;
@@ -142,11 +143,10 @@ protected Class> findClass(final String name) throws ClassNotFoundException {
*
* @param name Binary name of class.
* @param data Class data bytes.
- * @param cs CodeSource code source of the class bytes.
*
* @return Installed class.
*/
- synchronized Class> installClass(final String name, final byte[] data, final CodeSource cs) {
- return defineClass(name, data, 0, data.length, Objects.requireNonNull(cs));
+ synchronized Class> installClass(final String name, final byte[] data) {
+ return defineClass(name, data, 0, data.length);
}
}
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/StructureLoader.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/StructureLoader.java
index 6b0e54d8..6c97ee8a 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/StructureLoader.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/StructureLoader.java
@@ -32,7 +32,6 @@
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Modifier;
-import java.security.ProtectionDomain;
import java.util.Set;
import org.openjdk.nashorn.internal.codegen.ObjectClassGenerator;
@@ -129,6 +128,6 @@ private Class> generateClass(final String name, final String descriptor, final
final Context context = Context.getContext();
final byte[] code = new ObjectClassGenerator(context, dualFields).generate(descriptor);
- return defineClass(name, code, 0, code.length, new ProtectionDomain(null, getPermissions(null)));
+ return defineClass(name, code, 0, code.length);
}
}
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index 3f2a6edb..db2b63c8 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -51,7 +51,6 @@
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.security.ProtectionDomain;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
@@ -116,15 +115,17 @@
* to resemble Java anonymous classes) is actually equivalent to
new X(a, b, { ... })
.
*
* It is possible to create two different adapter classes: those that can have class-level overrides, and those that can
- * have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject, ProtectionDomain)}
- * or {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject, Lookup)} is invoked
+ * have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)}
+ * or {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)} is invoked
* with non-null {@code classOverrides} parameter, an adapter class is created that can have class-level overrides, and
* the passed script object will be used as the implementations for its methods, just as in the above case of the
* constructor taking a script object. Note that in the case of class-level overrides, a new adapter class is created on
* every invocation, and the implementation object is bound to the class, not to any instance. All created instances
* will share these functions. If it is required to have both class-level overrides and instance-level overrides, the
* class-level override adapter class should be subclassed with an instance-override adapter. Since adapters delegate to
- * super class when an overriding method handle is not specified, this will behave as expected. It is not possible to
+ * super class when an overriding method handle is not specified, this will behave as expected.
+ * TODO: see if below described limitation could be lifted now that java.security.ProtectionDomain is no longer used.
+ * It is not possible to
* have both class-level and instance-level overrides in the same class for security reasons: adapter classes are
* defined with a protection domain of their creator code, and an adapter class that has both class and instance level
* overrides would need to have two potentially different protection domains: one for class-based behavior and one for
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
index bbcd3950..23cd7917 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
@@ -25,8 +25,6 @@
package org.openjdk.nashorn.internal.runtime.linker;
-import java.security.ProtectionDomain;
-import java.security.SecureClassLoader;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -62,27 +60,23 @@ final class JavaAdapterClassLoader {
/**
* Loads the generated adapter class into the JVM.
* @param parentLoader the parent class loader for the generated class loader
- * @param protectionDomain the protection domain for the generated class
* @return the generated adapter class
*/
- StaticClass generateClass(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) {
- assert protectionDomain != null;
+ StaticClass generateClass(final ClassLoader parentLoader) {
try {
- return StaticClass.forClass(Class.forName(className, true, createClassLoader(parentLoader, protectionDomain)));
+ return StaticClass.forClass(Class.forName(className, true, createClassLoader(parentLoader)));
} catch (final ClassNotFoundException e) {
throw new AssertionError(e); // cannot happen
}
}
- // Note that the adapter class is created in the protection domain of the class/interface being
- // extended/implemented, and only the privileged global setter action class is generated in the protection domain
- // of Nashorn itself. Also note that the creation and loading of the global setter is deferred until it is
- // required by JVM linker, which will only happen on first invocation of any of the adapted method. We could defer
+ // Note that the creation and loading of the global setter is deferred until it is
+ // required by JVM linker, which will only happen on first invocation of any adapted method. We could defer
// it even more by separating its invocation into a separate static method on the adapter class, but then someone
// with ability to introspect on the class and use setAccessible(true) on it could invoke the method. It's a
// security tradeoff...
- private ClassLoader createClassLoader(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) {
- return new SecureClassLoader(parentLoader) {
+ private ClassLoader createClassLoader(final ClassLoader parentLoader) {
+ return new ClassLoader(parentLoader) {
private final ClassLoader myLoader = getClass().getClassLoader();
// the unnamed module into which adapter is loaded!
@@ -120,7 +114,7 @@ protected Class> findClass(final String name) throws ClassNotFoundException {
final Context ctx = Context.getContext();
DumpBytecode.dumpBytecode(ctx.getEnv(), ctx.getLogger(org.openjdk.nashorn.internal.codegen.Compiler.class), classBytes, name);
- return defineClass(name, classBytes, 0, classBytes.length, protectionDomain);
+ return defineClass(name, classBytes, 0, classBytes.length);
}
throw new ClassNotFoundException(name);
}
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
index 32190133..ae300129 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
@@ -29,14 +29,8 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
-import java.lang.invoke.VarHandle;
import java.lang.reflect.Modifier;
-import java.security.CodeSigner;
-import java.security.CodeSource;
-import java.security.Permissions;
-import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -47,7 +41,6 @@
import jdk.dynalink.StandardOperation;
import jdk.dynalink.beans.StaticClass;
import jdk.dynalink.linker.support.SimpleLinkRequest;
-import org.openjdk.nashorn.internal.runtime.Context;
import org.openjdk.nashorn.internal.runtime.ECMAErrors;
import org.openjdk.nashorn.internal.runtime.ECMAException;
import org.openjdk.nashorn.internal.runtime.ScriptFunction;
@@ -61,15 +54,14 @@
* generated that extends the specified superclass and implements the specified
* interfaces. (But see the discussion of class-based overrides for exceptions.)
*
- * The adapter class is generated in a new secure class loader that inherits
- * Nashorn's protection domain, and has either one of the original types' class
- * loader or the Nashorn's class loader as its parent - the parent class loader
- * is chosen so that all the original types and the Nashorn core classes are
- * visible from it (as the adapter will have constant pool references to
- * ScriptObject and ScriptFunction classes). In case none of the candidate class
- * loaders has visibility of all the required types, an error is thrown. The
- * class uses {@link JavaAdapterBytecodeGenerator} to generate the adapter class
- * itself; see its documentation for details about the generated class.
+ * The adapter class is generated in a new class loader and has either one of the
+ * original types' class loader or the Nashorn's class loader as its parent - the
+ * parent class loader is chosen so that all the original types and the Nashorn
+ * core classes are visible from it (as the adapter will have constant pool
+ * references to ScriptObject and ScriptFunction classes). In case none of the
+ * candidate class loaders has visibility of all the required types, an error is
+ * thrown. The class uses {@link JavaAdapterBytecodeGenerator} to generate the
+ * adapter class itself; see its documentation for details about the generated class.
*
* You normally don't use this class directly, but rather either create adapters
* from script using {@link org.openjdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)},
@@ -79,8 +71,6 @@
*/
public final class JavaAdapterFactory {
- private static final ProtectionDomain MINIMAL_PERMISSION_DOMAIN = createMinimalPermissionDomain();
-
/**
* A mapping from an original Class object to AdapterInfo representing the adapter for the class it represents.
*/
@@ -125,11 +115,6 @@ protected Boolean computeValue(final Class> type) {
* defined for all instances of the class, and can be further
* overridden on a per-instance basis by passing additional objects
* in the constructor.
- * @param lookup the lookup object identifying the caller class. The
- * generated adapter class will have the protection domain of the
- * caller class iff the lookup object is full-strength, otherwise it
- * will be completely unprivileged.
- *
* @return an adapter class. See this class' documentation for details on
* the generated adapter class.
*
@@ -137,20 +122,9 @@ protected Boolean computeValue(final Class> type) {
* generated because the original class is final, non-public, or has
* no public or protected constructors.
*/
- public static StaticClass getAdapterClassFor(final Class>[] types, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
- return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
- }
-
- private static StaticClass getAdapterClassFor(final Class>[] types, final ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
+ public static StaticClass getAdapterClassFor(final Class>[] types, final ScriptObject classOverrides) {
assert types != null && types.length > 0;
- return getAdapterInfo(types).getAdapterClass(classOverrides, protectionDomain);
- }
-
- private static ProtectionDomain getProtectionDomain(final MethodHandles.Lookup lookup) {
- if((lookup.lookupModes() & Lookup.PRIVATE) == 0) {
- return MINIMAL_PERMISSION_DOMAIN;
- }
- return lookup.lookupClass().getProtectionDomain();
+ return getAdapterInfo(types).getAdapterClass(classOverrides);
}
/**
@@ -174,7 +148,7 @@ private static ProtectionDomain getProtectionDomain(final MethodHandles.Lookup l
* @throws Exception if anything goes wrong
*/
public static MethodHandle getConstructor(final Class> sourceType, final Class> targetType, final MethodHandles.Lookup lookup) throws Exception {
- final StaticClass adapterClass = getAdapterClassFor(new Class>[] { targetType }, null, lookup);
+ final StaticClass adapterClass = getAdapterClassFor(new Class>[] { targetType }, null);
return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new SimpleLinkRequest(
new CallSiteDescriptor(lookup, StandardOperation.NEW,
MethodType.methodType(targetType, StaticClass.class, sourceType)), false,
@@ -265,61 +239,43 @@ enum ErrorOutcome {
private static class AdapterInfo {
private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptFunction.class, true);
- private static final VarHandle INSTANCE_ADAPTERS;
- static {
- try {
- INSTANCE_ADAPTERS = MethodHandles.lookup().findVarHandle(AdapterInfo.class, "instanceAdapters", Map.class);
- } catch (ReflectiveOperationException e) {
- throw new RuntimeException(e);
- }
- }
private final ClassLoader commonLoader;
// TODO: soft reference the JavaAdapterClassLoader objects. They can be recreated when needed.
private final JavaAdapterClassLoader classAdapterGenerator;
- private final JavaAdapterClassLoader instanceAdapterGenerator;
- private Map instanceAdapters;
+ private JavaAdapterClassLoader instanceAdapterGenerator;
+ private volatile StaticClass instanceAdapter;
final boolean autoConvertibleFromFunction;
AdapterInfo(final Class> superClass, final List> interfaces, final ClassAndLoader definingLoader) {
this.commonLoader = findCommonLoader(definingLoader);
final JavaAdapterBytecodeGenerator gen = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, false);
this.autoConvertibleFromFunction = gen.isAutoConvertibleFromFunction();
- instanceAdapterGenerator = gen.createAdapterClassLoader();
+ this.instanceAdapterGenerator = gen.createAdapterClassLoader();
this.classAdapterGenerator = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, true).createAdapterClassLoader();
}
- StaticClass getAdapterClass(final ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
- return classOverrides == null ? getInstanceAdapterClass(protectionDomain) :
- getClassAdapterClass(classOverrides, protectionDomain);
+ StaticClass getAdapterClass(final ScriptObject classOverrides) {
+ return classOverrides == null ? getInstanceAdapterClass() :
+ getClassAdapterClass(classOverrides);
}
- private StaticClass getInstanceAdapterClass(final ProtectionDomain protectionDomain) {
- CodeSource codeSource = protectionDomain.getCodeSource();
- if(codeSource == null) {
- codeSource = MINIMAL_PERMISSION_DOMAIN.getCodeSource();
- }
- var ia = instanceAdapters;
- if (ia == null) {
- var nia = new ConcurrentHashMap();
- @SuppressWarnings("unchecked")
- var xia = (Map)INSTANCE_ADAPTERS.compareAndExchange(this, null, nia);
- ia = xia == null ? nia : xia;
+ private StaticClass getInstanceAdapterClass() {
+ if (instanceAdapter == null) {
+ synchronized (this) {
+ if (instanceAdapter == null) {
+ instanceAdapter = instanceAdapterGenerator.generateClass(commonLoader);
+ instanceAdapterGenerator = null;
+ }
+ }
}
- return ia.computeIfAbsent(codeSource, cs -> {
- // Any "unknown source" code source will default to no permission domain.
- final ProtectionDomain effectiveDomain =
- cs.equals(MINIMAL_PERMISSION_DOMAIN.getCodeSource())
- ? MINIMAL_PERMISSION_DOMAIN : protectionDomain;
-
- return instanceAdapterGenerator.generateClass(commonLoader, effectiveDomain);
- });
+ return instanceAdapter;
}
- private StaticClass getClassAdapterClass(final ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
+ private StaticClass getClassAdapterClass(final ScriptObject classOverrides) {
JavaAdapterServices.setClassOverrides(classOverrides);
try {
- return classAdapterGenerator.generateClass(commonLoader, protectionDomain);
+ return classAdapterGenerator.generateClass(commonLoader);
} finally {
JavaAdapterServices.setClassOverrides(null);
}
@@ -345,12 +301,4 @@ private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader)
throw adaptationException(ErrorOutcome.NO_COMMON_LOADER, classAndLoader.getRepresentativeClass().getCanonicalName());
}
}
-
- private static ProtectionDomain createMinimalPermissionDomain() {
- // Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages.
- final Permissions permissions = new Permissions();
- permissions.add(new RuntimePermission("accessClassInPackage.org.openjdk.nashorn.internal.runtime"));
- permissions.add(new RuntimePermission("accessClassInPackage.org.openjdk.nashorn.internal.runtime.linker"));
- return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions);
- }
}
diff --git a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
index d8d64d2b..aff7214b 100644
--- a/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
+++ b/src/org.openjdk.nashorn/share/classes/org/openjdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
@@ -25,7 +25,6 @@
package org.openjdk.nashorn.internal.runtime.linker;
-import java.lang.invoke.MethodHandles;
import java.lang.reflect.Modifier;
import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.NamedOperation;
@@ -38,7 +37,6 @@
import jdk.dynalink.linker.LinkerServices;
import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.dynalink.linker.support.Guards;
-import org.openjdk.nashorn.internal.runtime.Context;
import org.openjdk.nashorn.internal.runtime.ECMAErrors;
/**
@@ -85,10 +83,7 @@ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final L
if (NashornLinker.isAbstractClass(receiverClass)) {
// Change this link request into a link request on the adapter class.
final Object[] args = request.getArguments();
- final MethodHandles.Lookup lookup =
- NashornCallSiteDescriptor.getLookupInternal(request.getCallSiteDescriptor());
-
- args[0] = JavaAdapterFactory.getAdapterClassFor(new Class>[] { receiverClass }, null, lookup);
+ args[0] = JavaAdapterFactory.getAdapterClassFor(new Class>[] { receiverClass }, null);
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.