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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # 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.SecureLookupSupplier;
import jdk.dynalink.internal.AccessControlContextFactory; import jdk.dynalink.internal.AccessControlContextFactory;
import jdk.dynalink.linker.support.Lookup; import jdk.dynalink.linker.support.Lookup;
import jdk.internal.module.Modules;
import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.CallerSensitive;
@ -180,57 +179,10 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
} }
private static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { private static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) {
try { return Lookup.unreflect(lookup, m);
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) { private static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) {
try { return Lookup.unreflectConstructor(lookup, c);
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. // is created, and invalidated forever once the second global is created.
private final AtomicReference<GlobalConstants> globalConstantsRef = new AtomicReference<>(); 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 * Get the current global scope
* @return 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) { private Module createModule(final String moduleName) {
final Module structMod = context.getStructLoader().getModule(); final Module structMod = context.getStructLoader().getModule();
final ModuleDescriptor descriptor final ModuleDescriptor.Builder builder =
= new ModuleDescriptor.Builder(moduleName) new ModuleDescriptor.Builder(moduleName)
.requires("java.base")
.requires("java.logging")
.requires(NASHORN_MODULE.getName()) .requires(NASHORN_MODULE.getName())
.requires(structMod.getName()) .requires(structMod.getName())
.conceals(SCRIPTS_PKG) .conceals(SCRIPTS_PKG);
.build();
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); final Module mod = Context.createModuleTrusted(structMod.getLayer(), descriptor, this);
loadModuleManipulator(); loadModuleManipulator();

View File

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

View File

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

View File

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

View File

@ -39,6 +39,7 @@ import jdk.dynalink.NamedOperation;
import jdk.dynalink.NoSuchDynamicMethodException; import jdk.dynalink.NoSuchDynamicMethodException;
import jdk.dynalink.Operation; import jdk.dynalink.Operation;
import jdk.dynalink.StandardOperation; import jdk.dynalink.StandardOperation;
import jdk.dynalink.beans.StaticClass;
import jdk.dynalink.linker.GuardedInvocation; import jdk.dynalink.linker.GuardedInvocation;
import jdk.dynalink.linker.GuardingDynamicLinker; import jdk.dynalink.linker.GuardingDynamicLinker;
import jdk.dynalink.linker.LinkRequest; import jdk.dynalink.linker.LinkRequest;
@ -234,6 +235,15 @@ public class DynamicLinkerFactoryTest {
@Test @Test
public void autoLoadedLinkerTest() { 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 DynamicLinkerFactory factory = newDynamicLinkerFactory(false);
final DynamicLinker linker = factory.createLinker(); final DynamicLinker linker = factory.createLinker();
@ -241,22 +251,21 @@ public class DynamicLinkerFactoryTest {
checkOneAutoLoadingError(factory); checkOneAutoLoadingError(factory);
final MethodType mt = MethodType.methodType(Object.class, Object.class); final MethodType mt = MethodType.methodType(Object.class, Object.class);
// create a callsite with TestLinkerOperation final CallSiteDescriptor testDescriptor = new CallSiteDescriptor(MethodHandles.publicLookup(),
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( new NamedOperation(StandardOperation.GET_METHOD, methodName), mt);
MethodHandles.publicLookup(), new TestLinkerOperation(), mt))); final CallSite cs = linker.link(new SimpleRelinkableCallSite(testDescriptor));
boolean reachedAutoLinker = false;
TrustedGuardingDynamicLinkerExporter.enable();
try { try {
cs.getTarget().invoke(new Object()); cs.getTarget().invoke(target);
} catch (final ReachedAutoLoadedDynamicLinkerException e) { // The linker was loaded and it observed our invocation
// TrustedGuardingDynamicLinkerExporter threw exception on TestLinkerOperation as expected! Assert.assertTrue(TrustedGuardingDynamicLinkerExporter.isLastCallSiteDescriptor(testDescriptor));
reachedAutoLinker = true;
} catch (final Throwable th) { } catch (final Throwable th) {
throw new RuntimeException(th); throw new RuntimeException(th);
} finally {
TrustedGuardingDynamicLinkerExporter.disable();
} }
Assert.assertTrue(reachedAutoLinker);
} }
@Test @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; package jdk.dynalink.test;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.linker.GuardingDynamicLinker; import jdk.dynalink.linker.GuardingDynamicLinker;
import jdk.dynalink.linker.GuardingDynamicLinkerExporter; import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
import jdk.dynalink.linker.LinkRequest; import jdk.dynalink.linker.LinkRequest;
@ -37,20 +37,32 @@ import jdk.dynalink.linker.LinkerServices;
*/ */
public final class TrustedGuardingDynamicLinkerExporter extends GuardingDynamicLinkerExporter { 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 @Override
public List<GuardingDynamicLinker> get() { public List<GuardingDynamicLinker> get() {
final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>(); return List.of(((GuardingDynamicLinker) (final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
linkers.add((GuardingDynamicLinker) (final LinkRequest linkRequest, final LinkerServices linkerServices) -> { if (enabled) {
// handle only the TestLinkerOperation instances lastDescriptor.set(linkRequest.getCallSiteDescriptor());
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 null;
} }
}); return null;
return linkers; }));
} }
} }