# HG changeset patch # User attila # Date 1476271395 -7200 # Node ID 1fced59dd44e48e4d9b8f4fd35a344001cb176da # Parent 08dc0d41209638f65008cadc87cf767f055c0f50 8167443: Nashorn static method linking bypasses autoexported linkers Reviewed-by: hannesw, sundar diff -r 08dc0d412096 -r 1fced59dd44e nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Tue Oct 11 09:49:43 2016 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Oct 12 13:23:15 2016 +0200 @@ -78,14 +78,17 @@ 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!! diff -r 08dc0d412096 -r 1fced59dd44e nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Tue Oct 11 09:49:43 2016 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Wed Oct 12 13:23:15 2016 +0200 @@ -68,7 +68,7 @@ @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(); diff -r 08dc0d412096 -r 1fced59dd44e nashorn/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java --- a/nashorn/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java Tue Oct 11 09:49:43 2016 +0200 +++ b/nashorn/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java Wed Oct 12 13:23:15 2016 +0200 @@ -39,6 +39,7 @@ 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 @@ @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 @@ 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 diff -r 08dc0d412096 -r 1fced59dd44e nashorn/test/src/jdk/dynalink/test/ReachedAutoLoadedDynamicLinkerException.java --- a/nashorn/test/src/jdk/dynalink/test/ReachedAutoLoadedDynamicLinkerException.java Tue Oct 11 09:49:43 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 { -} diff -r 08dc0d412096 -r 1fced59dd44e nashorn/test/src/jdk/dynalink/test/TestLinkerOperation.java --- a/nashorn/test/src/jdk/dynalink/test/TestLinkerOperation.java Tue Oct 11 09:49:43 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 { -} diff -r 08dc0d412096 -r 1fced59dd44e nashorn/test/src/jdk/dynalink/test/TrustedGuardingDynamicLinkerExporter.java --- a/nashorn/test/src/jdk/dynalink/test/TrustedGuardingDynamicLinkerExporter.java Tue Oct 11 09:49:43 2016 +0200 +++ b/nashorn/test/src/jdk/dynalink/test/TrustedGuardingDynamicLinkerExporter.java Wed Oct 12 13:23:15 2016 +0200 @@ -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 @@ */ public final class TrustedGuardingDynamicLinkerExporter extends GuardingDynamicLinkerExporter { + private static final ThreadLocal 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 get() { - final ArrayList 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 null; + return List.of(((GuardingDynamicLinker) (final LinkRequest linkRequest, final LinkerServices linkerServices) -> { + if (enabled) { + lastDescriptor.set(linkRequest.getCallSiteDescriptor()); } - }); - return linkers; + return null; + })); } }