--- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestReflectionHierarchy.java 2018-06-20 01:04:19.245258993 -0400 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2017, 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. + */ + +/* + * @test + * @bug 8046171 + * @summary Test access to private methods between nestmates where there + * is an inheritance hierarchy and we invoke private methods that + * exist in specific classes in the hierarchy. + * @run main TestReflectionHierarchy + * @run main/othervm -Dsun.reflect.noInflation=true TestReflectionHierarchy + */ + +// The first run will use NativeMethodAccessor and due to the limited number +// of calls we will not reach the inflation threshold. +// The second run disables inflation so we will use the GeneratedMethodAccessor +// instead. In this way both sets of Reflection classes are tested. + + +public class TestReflectionHierarchy { + + static class NestedA extends ExternalSuper { + static final String ID = "NestedA::priv_invoke"; + private String priv_invoke() { + return ID; + } + static void checkA(NestedA a) throws Throwable { + verifyEquals((String)NestedA.class. + getDeclaredMethod("priv_invoke", + new Class[0]). + invoke(a, new Object[0]), + NestedA.ID); + } + } + + static class NestedB extends NestedA { + static final String ID = "NestedB::priv_invoke"; + private String priv_invoke() { + return ID; + } + static void checkA(NestedA a) throws Throwable { + verifyEquals((String)NestedA.class. + getDeclaredMethod("priv_invoke", + new Class[0]). + invoke(a, new Object[0]), + NestedA.ID); + } + } + + static class NestedC extends NestedB { + static final String ID = "NestedC::priv_invoke"; + private String priv_invoke() { + return ID; + } + static void checkA(NestedA a) throws Throwable { + verifyEquals((String)NestedA.class. + getDeclaredMethod("priv_invoke", + new Class[0]). + invoke(a, new Object[0]), + NestedA.ID); + } + } + + static void checkA(NestedA a) throws Throwable { + verifyEquals((String)NestedA.class. + getDeclaredMethod("priv_invoke", + new Class[0]). + invoke(a, new Object[0]), + NestedA.ID); + } + + static void checkB(NestedB b) throws Throwable { + verifyEquals((String)NestedB.class. + getDeclaredMethod("priv_invoke", + new Class[0]). + invoke(b, new Object[0]), + NestedB.ID); + } + + static void checkC(NestedC c) throws Throwable { + verifyEquals((String)NestedC.class. + getDeclaredMethod("priv_invoke", + new Class[0]). + invoke(c, new Object[0]), + NestedC.ID); + } + + + // Access to private members of classes outside the nest is + // not permitted. These tests should throw IllegalAccessException + // at runtime. + + static void checkExternalSuper(ExternalSuper s) throws Throwable { + try { + ExternalSuper.class. + getDeclaredMethod("priv_invoke", new Class[0]). + invoke(s, new Object[0]); + throw new Error("Unexpected access to ExternalSuper.priv_invoke"); + } + catch (IllegalAccessException iae) { + System.out.println("Got expected exception accessing ExternalSuper.priv_invoke:" + iae); + } + } + + static void checkExternalSub(ExternalSub s) throws Throwable { + try { + ExternalSub.class. + getDeclaredMethod("priv_invoke", new Class[0]). + invoke(s, new Object[0]); + throw new Error("Unexpected access to ExternalSub.priv_invoke"); + } + catch (IllegalAccessException iae) { + System.out.println("Got expected exception accessing ExternalSub.priv_invoke:" + iae); + } + } + + static void verifyEquals(String actual, String expected) { + if (!actual.equals(expected)) { + throw new Error("Expected " + expected + " but got " + actual); + } + System.out.println("Check passed for " + expected); + } + + public static void main(String[] args) throws Throwable { + NestedA a = new NestedA(); + NestedB b = new NestedB(); + NestedC c = new NestedC(); + ExternalSub sub = new ExternalSub(); + ExternalSuper sup = new ExternalSuper(); + + checkExternalSuper(sup); + checkExternalSuper(a); + checkExternalSuper(b); + checkExternalSuper(c); + checkExternalSuper(sub); + + checkA(a); + checkA(b); + checkA(c); + checkA(sub); + + NestedA.checkA(a); + NestedA.checkA(b); + NestedA.checkA(c); + NestedA.checkA(sub); + + NestedB.checkA(a); + NestedB.checkA(b); + NestedB.checkA(c); + NestedB.checkA(sub); + + NestedC.checkA(a); + NestedC.checkA(b); + NestedC.checkA(c); + NestedC.checkA(sub); + + checkB(b); + checkB(c); + checkB(sub); + + checkC(c); + checkC(sub); + + checkExternalSub(sub); + } +} + +// Classes that are not part of the nest. +// Being non-public allows us to declare them in this file. + +class ExternalSuper { + static final String ID = "ExternalSuper::priv_invoke"; + private String priv_invoke() { + return ID; + } +} + + +class ExternalSub extends TestReflectionHierarchy.NestedC { + static final String ID = "ExternalSub::priv_invoke"; + private String priv_invoke() { + return ID; + } +}