This commit is contained in:
Lana Steuck 2016-10-13 23:03:33 +00:00
commit 347027f57c
11 changed files with 78 additions and 145 deletions

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2010, 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

View File

@ -100,7 +100,6 @@ import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.SecureLookupSupplier;
import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.linker.support.Lookup;
import jdk.internal.module.Modules;
import jdk.internal.reflect.CallerSensitive;
@ -180,57 +179,10 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
}
private static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) {
try {
return Lookup.unreflect(lookup, m);
} catch (final IllegalAccessError iae) {
if (addModuleRead(lookup, m)) {
try {
return Lookup.unreflect(lookup, m);
} catch (final IllegalAccessError e2) {
// fall through and throw original error as cause
}
}
throw iae;
}
}
private static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) {
try {
return Lookup.unreflectConstructor(lookup, c);
} catch (final IllegalAccessError iae) {
if (addModuleRead(lookup, c)) {
try {
return Lookup.unreflectConstructor(lookup, c);
} catch (final IllegalAccessError e2) {
// fall through and throw original error as cause
}
}
throw iae;
}
}
private static boolean addModuleRead(final MethodHandles.Lookup lookup, final Executable e) {
// Don't add module read link if this is not a CallerSensitive member
if (!e.isAnnotationPresent(CallerSensitive.class)) {
return false;
}
// If the lookup is public lookup, don't bother adding module read link!
// public lookup cannot unreflect caller sensitives anyway!
if (lookup == MethodHandles.publicLookup()) {
return false;
}
// try to add missing module read from using module to declararing module!
final Class<?> declClass = e.getDeclaringClass();
final Module useModule = lookup.lookupClass().getModule();
final Module declModule = declClass.getModule();
if (useModule != null && declModule != null && declModule.isExported(declClass.getPackageName())) {
Modules.addReads(useModule, declModule);
return true;
}
return false;
}
}

View File

@ -389,6 +389,15 @@ public final class Context {
// is created, and invalidated forever once the second global is created.
private final AtomicReference<GlobalConstants> globalConstantsRef = new AtomicReference<>();
// Are java.sql, java.sql.rowset modules found in the system?
static final boolean javaSqlFound, javaSqlRowsetFound;
static {
final Layer boot = Layer.boot();
javaSqlFound = boot.findModule("java.sql").isPresent();
javaSqlRowsetFound = boot.findModule("java.sql.rowset").isPresent();
}
/**
* Get the current global scope
* @return the current global scope

View File

@ -68,12 +68,23 @@ final class ScriptLoader extends NashornLoader {
private Module createModule(final String moduleName) {
final Module structMod = context.getStructLoader().getModule();
final ModuleDescriptor descriptor
= new ModuleDescriptor.Builder(moduleName)
final ModuleDescriptor.Builder builder =
new ModuleDescriptor.Builder(moduleName)
.requires("java.base")
.requires("java.logging")
.requires(NASHORN_MODULE.getName())
.requires(structMod.getName())
.conceals(SCRIPTS_PKG)
.build();
.conceals(SCRIPTS_PKG);
if (Context.javaSqlFound) {
builder.requires("java.sql");
}
if (Context.javaSqlRowsetFound) {
builder.requires("java.sql.rowset");
}
final ModuleDescriptor descriptor = builder.build();
final Module mod = Context.createModuleTrusted(structMod.getLayer(), descriptor, this);
loadModuleManipulator();

View File

@ -64,6 +64,7 @@ final class StructureLoader extends NashornLoader {
private Module createModule(final String moduleName) {
final ModuleDescriptor descriptor
= new ModuleDescriptor.Builder(moduleName)
.requires("java.base")
.requires(NASHORN_MODULE.getName())
.conceals(SCRIPTS_PKG)
.build();

View File

@ -78,14 +78,17 @@ public final class Bootstrap {
prioritizedLinkers = new GuardingDynamicLinker[] {
new NashornLinker(),
new NashornPrimitiveLinker(),
new NashornStaticClassLinker(beansLinker),
new BoundCallableLinker(),
new JavaSuperAdapterLinker(beansLinker),
new JSObjectLinker(nashornBeansLinker),
new BrowserJSObjectLinker(nashornBeansLinker),
new ReflectionCheckLinker()
};
fallbackLinkers = new GuardingDynamicLinker[] {nashornBeansLinker, new NashornBottomLinker() };
fallbackLinkers = new GuardingDynamicLinker[] {
new NashornStaticClassLinker(beansLinker),
nashornBeansLinker,
new NashornBottomLinker()
};
}
// do not create me!!

View File

@ -68,7 +68,7 @@ final class NashornStaticClassLinker implements TypeBasedGuardingDynamicLinker {
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
final Object self = request.getReceiver();
if (self.getClass() != StaticClass.class) {
if (self == null || self.getClass() != StaticClass.class) {
return null;
}
final Class<?> receiverClass = ((StaticClass) self).getRepresentedClass();

View File

@ -39,6 +39,7 @@ import jdk.dynalink.NamedOperation;
import jdk.dynalink.NoSuchDynamicMethodException;
import jdk.dynalink.Operation;
import jdk.dynalink.StandardOperation;
import jdk.dynalink.beans.StaticClass;
import jdk.dynalink.linker.GuardedInvocation;
import jdk.dynalink.linker.GuardingDynamicLinker;
import jdk.dynalink.linker.LinkRequest;
@ -234,6 +235,15 @@ public class DynamicLinkerFactoryTest {
@Test
public void autoLoadedLinkerTest() {
testAutoLoadedLinkerInvoked(new Object(), "toString");
}
@Test
public void autoLoadedLinkerSeesStaticMethod() {
testAutoLoadedLinkerInvoked(StaticClass.forClass(System.class), "currentTimeMillis");
}
private static void testAutoLoadedLinkerInvoked(final Object target, final String methodName) {
final DynamicLinkerFactory factory = newDynamicLinkerFactory(false);
final DynamicLinker linker = factory.createLinker();
@ -241,22 +251,21 @@ public class DynamicLinkerFactoryTest {
checkOneAutoLoadingError(factory);
final MethodType mt = MethodType.methodType(Object.class, Object.class);
// create a callsite with TestLinkerOperation
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
MethodHandles.publicLookup(), new TestLinkerOperation(), mt)));
boolean reachedAutoLinker = false;
final CallSiteDescriptor testDescriptor = new CallSiteDescriptor(MethodHandles.publicLookup(),
new NamedOperation(StandardOperation.GET_METHOD, methodName), mt);
final CallSite cs = linker.link(new SimpleRelinkableCallSite(testDescriptor));
TrustedGuardingDynamicLinkerExporter.enable();
try {
cs.getTarget().invoke(new Object());
} catch (final ReachedAutoLoadedDynamicLinkerException e) {
// TrustedGuardingDynamicLinkerExporter threw exception on TestLinkerOperation as expected!
reachedAutoLinker = true;
cs.getTarget().invoke(target);
// The linker was loaded and it observed our invocation
Assert.assertTrue(TrustedGuardingDynamicLinkerExporter.isLastCallSiteDescriptor(testDescriptor));
} catch (final Throwable th) {
throw new RuntimeException(th);
} finally {
TrustedGuardingDynamicLinkerExporter.disable();
}
Assert.assertTrue(reachedAutoLinker);
}
@Test

View File

@ -1,33 +0,0 @@
/*
* Copyright (c) 2015, 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.dynalink.test;
/**
* Exception used to signal to the test method that the control has reached auto loaded
* dynamic linker.
*/
public final class ReachedAutoLoadedDynamicLinkerException extends RuntimeException {
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2015, 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.dynalink.test;
import jdk.dynalink.Operation;
public final class TestLinkerOperation implements Operation {
}

View File

@ -25,8 +25,8 @@
package jdk.dynalink.test;
import java.util.ArrayList;
import java.util.List;
import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.linker.GuardingDynamicLinker;
import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
import jdk.dynalink.linker.LinkRequest;
@ -37,20 +37,32 @@ import jdk.dynalink.linker.LinkerServices;
*/
public final class TrustedGuardingDynamicLinkerExporter extends GuardingDynamicLinkerExporter {
private static final ThreadLocal<CallSiteDescriptor> lastDescriptor = new ThreadLocal<>();
private static boolean enabled = false;
public static void enable() {
reset(true);
}
public static void disable() {
reset(false);
}
public static boolean isLastCallSiteDescriptor(final CallSiteDescriptor desc) {
return lastDescriptor.get() == desc;
}
private static void reset(final boolean enable) {
lastDescriptor.set(null);
enabled = enable;
}
@Override
public List<GuardingDynamicLinker> get() {
final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
linkers.add((GuardingDynamicLinker) (final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
// handle only the TestLinkerOperation instances
if (linkRequest.getCallSiteDescriptor().getOperation() instanceof TestLinkerOperation) {
System.out.println("inside " + this.getClass().getName());
// throw exception to signal to the test method that the control has reached here!
throw new ReachedAutoLoadedDynamicLinkerException();
} else {
// any other operation!
return List.of(((GuardingDynamicLinker) (final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
if (enabled) {
lastDescriptor.set(linkRequest.getCallSiteDescriptor());
}
return null;
}
});
return linkers;
}));
}
}