--- old/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp 2018-05-30 08:10:10.046459229 -0400 +++ new/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp 2018-05-30 08:10:08.558372760 -0400 @@ -3608,10 +3608,10 @@ __ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_vfinal_shift); __ bfalse(CCR0, LnotVFinal); - __ check_klass_subtype(Rrecv_klass, Rinterface_klass, Rscratch, Rscratch1, subtype); + __ check_klass_subtype(Rrecv_klass, Rinterface_klass, Rscratch1, Rscratch2, L_subtype); // If we get here the typecheck failed __ b(L_no_such_interface); - __ bind(subtype); + __ bind(L_subtype); // do the call --- old/src/hotspot/cpu/s390/templateTable_s390.cpp 2018-05-30 08:10:16.866855541 -0400 +++ new/src/hotspot/cpu/s390/templateTable_s390.cpp 2018-05-30 08:10:15.378769072 -0400 @@ -3636,7 +3636,7 @@ NearLabel subtype, no_such_interface; - __ check_klass_subtype(klass, interface, Z_tmp_2, Z_temp_3, subtype); + __ check_klass_subtype(klass, interface, Z_tmp_2, Z_tmp_3, subtype); // If we get here the typecheck failed __ z_bru(no_such_interface); __ bind(subtype); --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/NestmatesJNI.java 2018-05-30 08:10:22.163163292 -0400 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 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. + */ + +/** + * Utility class for invoking methods and constructors and accessing fields + * via JNI. + */ +public class NestmatesJNI { + + static { + System.loadLibrary("NestmatesJNI"); + } + + public static native void callVoidVoid(Object target, String definingClassName, String methodName, boolean virtual); + + public static native String callStringVoid(Object target, String definingClassName, String methodName, boolean virtual); + + public static native void callStaticVoidVoid(String definingClassName, String methodName); + + public static Object newInstance(String definingClassName, String sig, Object outerThis) { + return newInstance0(definingClassName, "", sig, outerThis); + } + + private static native Object newInstance0(String definingClassName, String method_name, String sig, Object outerThis); + + public static native int getIntField(Object target, String definingClassName, String fieldName); + + public static native void setIntField(Object target, String definingClassName, String fieldName, int newVal); + + public static native int getStaticIntField(String definingClassName, String fieldName); + + public static native void setStaticIntField(String definingClassName, String fieldName, int newVal); + +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/libNestmatesJNI.c 2018-05-30 08:10:28.963558441 -0400 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, 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. + */ + +#include + +// boolean flag for static versus non-static +#define STATIC 1 +#define NON_STATIC 0 + +// Helper methods to get class/method/field IDs + +static void getClassID(JNIEnv *env, + jstring defining_class_name, + jclass* clazz) { + const char* name = (*env)->GetStringUTFChars(env, defining_class_name, NULL); + if (name != NULL) { + *clazz = (*env)->FindClass(env, name); + (*env)->ReleaseStringUTFChars(env, defining_class_name, name); + } +} + +static void getClassAndMethodID(JNIEnv *env, + int is_static, + jstring defining_class_name, + jstring method_name, + const char* sig, + jmethodID* m_id, jclass* clazz) { + getClassID(env, defining_class_name, clazz); + if (*clazz != NULL) { + const char* name = (*env)->GetStringUTFChars(env, method_name, NULL); + if (name != NULL) { + if (is_static) { + *m_id = (*env)->GetStaticMethodID(env, *clazz, name, sig); + } else { + *m_id = (*env)->GetMethodID(env, *clazz, name, sig); + } + (*env)->ReleaseStringUTFChars(env, method_name, name); + } + } +} + +static void getClassAndFieldID(JNIEnv *env, + int is_static, + jstring defining_class_name, + jstring field_name, + const char* sig, + jfieldID* m_id, jclass* clazz) { + getClassID(env, defining_class_name, clazz); + if (*clazz != NULL) { + const char* name = (*env)->GetStringUTFChars(env, field_name, NULL); + if (name != NULL) { + if (is_static) { + *m_id = (*env)->GetStaticFieldID(env, *clazz, name, sig); + } else { + *m_id = (*env)->GetFieldID(env, *clazz, name, sig); + } + (*env)->ReleaseStringUTFChars(env, field_name, name); + } + } +} + +JNIEXPORT void JNICALL +Java_NestmatesJNI_callVoidVoid(JNIEnv *env, jclass unused, + jobject target, + jstring defining_class_name, + jstring method_name, + jboolean virtual) { + + // Lookup "void method_name()" in defining_class_name, and if it exists + // call target.method_name() using a virtual or non-virtual invocation + + jmethodID m_id = NULL; + jclass clazz = NULL; + getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name, + "()V", &m_id, &clazz); + if (m_id != NULL && clazz != NULL) { + if (!virtual) { + (*env)->CallNonvirtualVoidMethod(env, target, clazz, m_id); + } else { + (*env)->CallVoidMethod(env, target, m_id); + } + } +} + +JNIEXPORT jobject JNICALL +Java_NestmatesJNI_callStringVoid(JNIEnv *env, jclass unused, + jobject target, + jstring defining_class_name, + jstring method_name, + jboolean virtual) { + + // Lookup "String method_name()" in defining_class_name, and if it exists + // call target.method_name() using a virtual or non-virtual invocation + + jmethodID m_id = NULL; + jclass clazz = NULL; + getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name, + "()Ljava/lang/String;", &m_id, &clazz); + if (m_id != NULL && clazz != NULL) { + if (!virtual) { + return (*env)->CallNonvirtualObjectMethod(env, target, clazz, m_id); + } else { + return (*env)->CallObjectMethod(env, target, m_id); + } + } + return NULL; +} + +JNIEXPORT jobject JNICALL +Java_NestmatesJNI_newInstance0(JNIEnv *env, jclass unused, + jstring defining_class_name, + jstring method_name, + jstring sig, + jobject outerThis) { + + // Lookup the no-user-arg constructor in defining_class_name using sig, + // and use it to create an instance of the class, and return it. For + // inner classes we need an outerThis reference to pass to the constructor. + + jmethodID m_id = NULL; + jclass clazz = NULL; + const char* _sig = (*env)->GetStringUTFChars(env, sig, NULL); + getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name, + _sig, &m_id, &clazz); + (*env)->ReleaseStringUTFChars(env, sig, _sig); + if (m_id != NULL && clazz != NULL) { + return (*env)->NewObject(env, clazz, m_id, outerThis); + } + return NULL; +} + +JNIEXPORT void JNICALL +Java_NestmatesJNI_callStaticVoidVoid(JNIEnv *env, jclass unused, + jstring defining_class_name, + jstring method_name) { + + // Lookup "static void method_name()" in defining_class_name, and if it exists + // invoke it. + + jmethodID m_id = NULL; + jclass clazz = NULL; + getClassAndMethodID(env, STATIC, defining_class_name, method_name, + "()V", &m_id, &clazz); + if (m_id != NULL && clazz != NULL) { + (*env)->CallStaticVoidMethod(env, clazz, m_id); + } +} + +JNIEXPORT jint JNICALL +Java_NestmatesJNI_getIntField(JNIEnv *env, jclass unused, + jobject target, + jstring defining_class_name, + jstring field_name) { + + // Lookup field field_name in defining_class_name, and if it exists + // return its value. + + jfieldID f_id = NULL; + jclass clazz = NULL; + getClassAndFieldID(env, NON_STATIC, defining_class_name, field_name, + "I", &f_id, &clazz); + if (f_id != NULL && clazz != NULL) { + return (*env)->GetIntField(env, target, f_id); + } + return -1; +} + +JNIEXPORT void JNICALL +Java_NestmatesJNI_setIntField(JNIEnv *env, jclass unused, + jobject target, + jstring defining_class_name, + jstring field_name, + jint newVal) { + + // Lookup field field_name in defining_class_name, and if it exists + // set it to newVal. + + jfieldID f_id = NULL; + jclass clazz = NULL; + getClassAndFieldID(env, NON_STATIC, defining_class_name, field_name, + "I", &f_id, &clazz); + if (f_id != NULL && clazz != NULL) { + (*env)->SetIntField(env, target, f_id, newVal); + } +} + +JNIEXPORT jint JNICALL +Java_NestmatesJNI_getStaticIntField(JNIEnv *env, jclass unused, + jstring defining_class_name, + jstring field_name) { + + // Lookup field field_name in defining_class_name, and if it exists + // return its value. + + jfieldID f_id = NULL; + jclass clazz = NULL; + getClassAndFieldID(env, STATIC, defining_class_name, field_name, + "I", &f_id, &clazz); + if (f_id != NULL && clazz != NULL) { + return (*env)->GetStaticIntField(env, clazz, f_id); + } + return -1; +} + +JNIEXPORT void JNICALL +Java_NestmatesJNI_setStaticIntField(JNIEnv *env, jclass unused, + jstring defining_class_name, + jstring field_name, + jint newVal) { + + // Lookup field field_name in defining_class_name, and if it exists + // set it to newVal. + + jfieldID f_id = NULL; + jclass clazz = NULL; + getClassAndFieldID(env, STATIC, defining_class_name, field_name, + "I", &f_id, &clazz); + if (f_id != NULL && clazz != NULL) { + (*env)->SetStaticIntField(env, clazz, f_id, newVal); + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestJNI.java 2018-05-30 08:10:35.807956143 -0400 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2018, 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 JNI access to private constructors between nestmates and nest-host + * using different flavours of named nested types using core reflection + * @compile ../NestmatesJNI.java + * @run main/othervm/native TestJNI + * @run main/othervm/native -Xcheck:jni TestJNI + */ +public class TestJNI { + + // Unlike reflection, the calling context is not relevant to JNI + // calls, but we keep the same structure as the reflection tests. + + + // All constructors are private to ensure nestmate access checks apply + + // All doConstruct methods are public so they don't involve nestmate access + + private TestJNI() {} + + // The various nestmates + + // Note: No constructor on interfaces so no StaticIface variants + + static interface StaticIface { + + // Methods that will access private constructors of nestmates. + + default void doConstruct(TestJNI o) throws Throwable { + Object obj = newInstance(o.getClass()); + } + default void doConstruct(TestJNI outerThis, InnerNested o) throws Throwable { + Object obj = newInstance(o.getClass(), outerThis); + } + default void doConstruct(StaticNested o) throws Throwable { + Object obj = newInstance(o.getClass()); + } + } + + static class StaticNested { + + private StaticNested() {} + + // Methods that will access private constructors of nestmates. + // The arg is a dummy for overloading purposes + + public void doConstruct(TestJNI o) throws Throwable { + Object obj = newInstance(o.getClass()); + } + public void doConstruct(TestJNI outerThis, InnerNested o) throws Throwable { + Object obj = newInstance(o.getClass(), outerThis); + } + public void doConstruct(StaticNested o) throws Throwable { + Object obj = newInstance(o.getClass()); + } + } + + class InnerNested { + + private InnerNested() {} + + // Methods that will access private constructors of nestmates. + // The arg is a dummy for overloading purposes + + public void doConstruct(TestJNI o) throws Throwable { + Object obj = newInstance(o.getClass()); + } + public void doConstruct(TestJNI outerThis, InnerNested o) throws Throwable { + Object obj = newInstance(o.getClass(), outerThis); + } + public void doConstruct(StaticNested o) throws Throwable { + Object obj = newInstance(o.getClass()); + } + } + + public static void main(String[] args) throws Throwable { + // These initial constructions test nest-host access to members + + TestJNI o = newInstance(TestJNI.class); + StaticNested s = (StaticNested) newInstance(StaticNested.class); + InnerNested i = (InnerNested) newInstance(InnerNested.class, o); + + // We need a StaticIface instance to call doConstruct on + StaticIface intf = new StaticIface() {}; + + s.doConstruct(o); + s.doConstruct(o, i); + s.doConstruct(s); + + i.doConstruct(o); + i.doConstruct(o, i); + i.doConstruct(s); + + intf.doConstruct(o); + intf.doConstruct(o, i); + intf.doConstruct(s); + } + + static T newInstance(Class klass) { + return newInstance(klass, null); + } + + static T newInstance(Class klass, Object outerThis) { + String sig = (outerThis == null) ? + "()V" : + "(L" + outerThis.getClass().getName() + ";)V"; + String definingClass = klass.getName(); + String desc = " Invocation of constructor " + definingClass + sig; + try { + T ret = (T) NestmatesJNI.newInstance(definingClass, sig, outerThis); + System.out.println(desc + " - passed"); + return ret; + } + catch (Throwable t) { + throw new Error(desc + ": Unexpected exception: " + t, t); + } + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/privateFields/TestJNI.java 2018-05-30 08:10:42.556348266 -0400 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2018, 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 JNI access to private fields between nestmates and nest-host + * using different flavours of named nested types + * @compile ../NestmatesJNI.java + * @run main/othervm/native TestJNI + * @run main/othervm/native -Xcheck:jni TestJNI + */ +public class TestJNI { + + // Private field of nest-host for nestmates to access + private int priv_field; + + static final String FIELD = "priv_field"; + + // public constructor so we aren't relying on private access + public TestJNI() {} + + // Methods that will access private fields of nestmates + + // NOTE: No StaticIface variants as interfaces can't have instance fields + + void access_priv(TestJNI o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + void access_priv(InnerNested o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + void access_priv(StaticNested o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + + // The various nestmates + + static interface StaticIface { + + // Methods that will access private fields of nestmates + + default void access_priv(TestJNI o) { + int priv_field = getAndInc(o, o.getClass(), FIELD); + } + default void access_priv(InnerNested o) { + int priv_field = getAndInc(o, o.getClass(), FIELD); + } + default void access_priv(StaticNested o) { + int priv_field = getAndInc(o, o.getClass(), FIELD); + } + } + + static class StaticNested { + + private int priv_field; + + // public constructor so we aren't relying on private access + public StaticNested() {} + + // Methods that will access private fields of nestmates + + void access_priv(TestJNI o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + void access_priv(InnerNested o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + void access_priv(StaticNested o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + } + + class InnerNested { + + private int priv_field; + + // public constructor so we aren't relying on private access + public InnerNested() {} + + void access_priv(TestJNI o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + void access_priv(InnerNested o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + void access_priv(StaticNested o) { + this.priv_field = getAndInc(o, o.getClass(), FIELD); + } + } + + public static void main(String[] args) { + TestJNI o = new TestJNI(); + StaticNested s = new StaticNested(); + InnerNested i = o.new InnerNested(); + StaticIface intf = new StaticIface() {}; + + o.access_priv(new TestJNI()); + o.access_priv(i); + o.access_priv(s); + + s.access_priv(o); + s.access_priv(i); + s.access_priv(new StaticNested()); + + i.access_priv(o); + i.access_priv(o.new InnerNested()); + i.access_priv(s); + + intf.access_priv(o); + intf.access_priv(i); + intf.access_priv(s); + } + + static int getAndInc(Object target, Class klass, String field) { + String definingClass = klass.getName(); + String desc = "Access to field " + + definingClass + "." + field + " on instance of class " + + target.getClass().getName(); + int first, second; + try { + first = NestmatesJNI.getIntField(target, definingClass, field); + NestmatesJNI.setIntField(target, definingClass, field, (first + 1)); + second = NestmatesJNI.getIntField(target, definingClass, field); + } + catch (Throwable t) { + throw new Error(desc + ": Unexpected exception: " + t, t); + } + if (second != first + 1) { + throw new Error(desc + ": wrong field values: first=" + first + + ", second=" + second + " (should equal first+1)"); + } + System.out.println(desc + " - passed"); + return first; + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNI.java 2018-05-30 08:10:49.292739691 -0400 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2018, 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 JNI access to private methods between nestmates and nest-host + * using different flavours of named nested types + * @compile ../NestmatesJNI.java + * @run main/othervm/native TestJNI + * @run main/othervm/native -Xcheck:jni TestJNI + */ +public class TestJNI { + + // Unlike reflection, the calling context is not relevant to JNI + // calls, but we keep the same structure as the reflection tests. + + static final String METHOD = "priv_invoke"; + + // Private method of nest-host for nestmates to access + private void priv_invoke() { + System.out.println("TestJNI::priv_invoke"); + } + + // public constructor so we aren't relying on private access + public TestJNI() {} + + // Methods that will access private methods of nestmates + + void access_priv(TestJNI o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(InnerNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(StaticNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(o, StaticIface.class, METHOD, true); + doCall(o, StaticIface.class, METHOD, false); + } + + // The various nestmates + + static interface StaticIface { + + private void priv_invoke() { + System.out.println("StaticIface::priv_invoke"); + } + + // Methods that will access private methods of nestmates + + default void access_priv(TestJNI o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + default void access_priv(InnerNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + default void access_priv(StaticNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + default void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(o, StaticIface.class, METHOD, true); + doCall(o, StaticIface.class, METHOD, false); + } + } + + static class StaticNested { + + private void priv_invoke() { + System.out.println("StaticNested::priv_invoke"); + } + + // public constructor so we aren't relying on private access + public StaticNested() {} + + // Methods that will access private methods of nestmates + + void access_priv(TestJNI o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(InnerNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(StaticNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(o, StaticIface.class, METHOD, true); + doCall(o, StaticIface.class, METHOD, false); + } + } + + class InnerNested { + + private void priv_invoke() { + System.out.println("InnerNested::priv_invoke"); + } + + // public constructor so we aren't relying on private access + public InnerNested() {} + + void access_priv(TestJNI o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(InnerNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(StaticNested o) { + doCall(o, o.getClass(), METHOD, true); + doCall(o, o.getClass(), METHOD, false); + } + void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(o, StaticIface.class, METHOD, true); + doCall(o, StaticIface.class, METHOD, false); + } + } + + public static void main(String[] args) { + TestJNI o = new TestJNI(); + StaticNested s = new StaticNested(); + InnerNested i = o.new InnerNested(); + StaticIface intf = new StaticIface() {}; + + o.access_priv(new TestJNI()); + o.access_priv(i); + o.access_priv(s); + o.access_priv(intf); + + s.access_priv(o); + s.access_priv(i); + s.access_priv(new StaticNested()); + s.access_priv(intf); + + i.access_priv(o); + i.access_priv(o.new InnerNested()); + i.access_priv(s); + i.access_priv(intf); + + intf.access_priv(o); + intf.access_priv(i); + intf.access_priv(s); + intf.access_priv(new StaticIface(){}); + } + + + static void doCall(Object target, Class klass, String method, + boolean virtual) { + String definingClass = klass.getName(); + String desc = (virtual ? "Virtual" : "Nonvirtual") + " Invocation of " + + definingClass + "." + method + " on instance of class " + + target.getClass().getName(); + try { + NestmatesJNI.callVoidVoid(target, definingClass, method, virtual); + System.out.println(desc + " - passed"); + } + catch (Throwable t) { + throw new Error(desc + ": Unexpected exception: " + t, t); + } + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNIHierarchy.java 2018-05-30 08:10:56.045132041 -0400 @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2018, 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. + * @compile ../NestmatesJNI.java + * @run main/othervm/native TestJNIHierarchy + * @run main/othervm/native -Xcheck:jni TestJNIHierarchy + */ + +public class TestJNIHierarchy { + + // Unlike reflection, the calling context is not relevant to JNI + // calls, but we keep the same structure as the reflection tests. + + static final String METHOD = "priv_invoke"; + + static class NestedA extends ExternalSuper { + static final String ID = "NestedA::priv_invoke"; + private String priv_invoke() { + return ID; + } + static void checkA(NestedA a) { + String res = NestmatesJNI.callStringVoid(a, + NestedA.class.getName(), + METHOD, + true); + verifyEquals(res, NestedA.ID); + res = NestmatesJNI.callStringVoid(a, + NestedA.class.getName(), + METHOD, + false); + verifyEquals(res, 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) { + String res = NestmatesJNI.callStringVoid(a, + NestedA.class.getName(), + METHOD, + true); + verifyEquals(res, NestedA.ID); + + res = NestmatesJNI.callStringVoid(a, + NestedA.class.getName(), + METHOD, + false); + verifyEquals(res, 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) { + String res = NestmatesJNI.callStringVoid(a, + NestedA.class.getName(), + METHOD, + true); + verifyEquals(res, NestedA.ID); + } + } + + static void checkA(NestedA a) { + String res = NestmatesJNI.callStringVoid(a, + NestedA.class.getName(), + METHOD, + true); + verifyEquals(res, NestedA.ID); + + res = NestmatesJNI.callStringVoid(a, + NestedA.class.getName(), + METHOD, + false); + verifyEquals(res, NestedA.ID); + } + + static void checkB(NestedB b) { + String res = NestmatesJNI.callStringVoid(b, + NestedB.class.getName(), + METHOD, + true); + verifyEquals(res, NestedB.ID); + + res = NestmatesJNI.callStringVoid(b, + NestedB.class.getName(), + METHOD, + false); + verifyEquals(res, NestedB.ID); + + } + + static void checkC(NestedC c) { + String res = NestmatesJNI.callStringVoid(c, + NestedC.class.getName(), + METHOD, + true); + verifyEquals(res, NestedC.ID); + + res = NestmatesJNI.callStringVoid(c, + NestedC.class.getName(), + METHOD, + false); + verifyEquals(res, NestedC.ID); + } + + + // Access to private members of classes outside the nest is + // not permitted in general, but JNI ignores all access checks. + + static void checkExternalSuper(ExternalSuper s) { + String res = NestmatesJNI.callStringVoid(s, + ExternalSuper.class.getName(), + METHOD, + true); + verifyEquals(res, ExternalSuper.ID); + + res = NestmatesJNI.callStringVoid(s, + ExternalSuper.class.getName(), + METHOD, + false); + verifyEquals(res, ExternalSuper.ID); + } + + static void checkExternalSub(ExternalSub s) { + String res = NestmatesJNI.callStringVoid(s, + ExternalSub.class.getName(), + METHOD, + true); + verifyEquals(res, ExternalSub.ID); + + res = NestmatesJNI.callStringVoid(s, + ExternalSub.class.getName(), + METHOD, + false); + verifyEquals(res, ExternalSub.ID); + } + + 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) { + 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 TestJNIHierarchy.NestedC { + static final String ID = "ExternalSub::priv_invoke"; + private String priv_invoke() { + return ID; + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/privateStaticFields/TestJNI.java 2018-05-30 08:11:04.093599699 -0400 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2018, 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 JNI access to private static fields between nestmates and nest-host + * using different flavours of named nested types + * @compile ../NestmatesJNI.java + * @run main/othervm/native TestJNI + * @run main/othervm/native -Xcheck:jni TestJNI + */ +public class TestJNI { + + // Private field of nest-host for nestmates to access + private static int priv_field; + + static final String FIELD = "priv_field"; + + // public constructor so we aren't relying on private access + public TestJNI() {} + + // Methods that will access private static fields of nestmates + + // NOTE: No InnerNested calls in this test because non-static nested types + // can't have static fields. Also no StaticIface calls as static interface + // fields must be public (and final) + + void access_priv(TestJNI o) { + priv_field = getAndInc(o.getClass(), FIELD); + } + void access_priv(StaticNested o) { + priv_field = getAndInc(o.getClass(), FIELD); + } + + // The various nestmates + + static interface StaticIface { + + // Methods that will access private static fields of nestmates + + default void access_priv(TestJNI o) { + int priv_field = getAndInc(o.getClass(), FIELD); + } + default void access_priv(StaticNested o) { + int priv_field = getAndInc(o.getClass(), FIELD); + } + } + + static class StaticNested { + + private static int priv_field; + + // public constructor so we aren't relying on private access + public StaticNested() {} + + // Methods that will access private static fields of nestmates + + void access_priv(TestJNI o) { + priv_field = getAndInc(o.getClass(), FIELD); + } + void access_priv(StaticNested o) { + priv_field = getAndInc(o.getClass(), FIELD); + } + } + + class InnerNested { + + // public constructor so we aren't relying on private access + public InnerNested() {} + + void access_priv(TestJNI o) { + int priv_field = getAndInc(o.getClass(), FIELD); + } + void access_priv(StaticNested o) { + int priv_field = getAndInc(o.getClass(), FIELD); + } + } + + public static void main(String[] args) { + TestJNI o = new TestJNI(); + StaticNested s = new StaticNested(); + InnerNested i = o.new InnerNested(); + StaticIface intf = new StaticIface() {}; + + o.access_priv(new TestJNI()); + o.access_priv(s); + + s.access_priv(o); + s.access_priv(new StaticNested()); + + i.access_priv(o); + i.access_priv(s); + + intf.access_priv(o); + intf.access_priv(s); + } + + static int getAndInc(Class klass, String field) { + String definingClass = klass.getName(); + String desc = "Access to static field " + definingClass + "." + field; + int first, second; + try { + first = NestmatesJNI.getStaticIntField(definingClass, field); + NestmatesJNI.setStaticIntField(definingClass, field, (first + 1)); + second = NestmatesJNI.getStaticIntField(definingClass, field); + } + catch (Throwable t) { + throw new Error(desc + ": Unexpected exception: " + t, t); + } + if (second != first + 1) { + throw new Error(desc + ": wrong field values: first=" + first + + ", second=" + second + " (should equal first+1)"); + } + System.out.println(desc + " - passed"); + return first; + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/hotspot/jtreg/runtime/Nestmates/privateStaticMethods/TestJNI.java 2018-05-30 08:11:10.865993207 -0400 @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2018, 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 JNI access to private methods between nestmates and nest-host + * using different flavours of named nested types + * @compile ../NestmatesJNI.java + * @run main/othervm/native TestJNI + * @run main/othervm/native -Xcheck:jni TestJNI + */ +public class TestJNI { + + // Unlike reflection, the calling context is not relevant to JNI + // calls, but we keep the same structure as the reflection tests. + + // Private static method of nest-host for nestmates to access + private static void priv_static_invoke() { + System.out.println("TestJNI::priv_static_invoke"); + } + + static final String METHOD = "priv_static_invoke"; + + // public constructor so we aren't relying on private access + public TestJNI() {} + + // Methods that will access private static methods of nestmates + // We use the arguments for overloading purposes and use the fact + // you can invoke a static method through an object reference for + // convenience. Except for static interface methods of course. + + // NOTE: No InnerNested calls in this test because non-static nested types + // can't have static method + + void access_priv(TestJNI o) { + doCall(o.getClass(), METHOD); + } + void access_priv(StaticNested o) { + doCall(o.getClass(), METHOD); + } + void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(StaticIface.class, METHOD); + } + + // The various nestmates + + static interface StaticIface { + + private static void priv_static_invoke() { + System.out.println("StaticIface::priv_static_invoke"); + } + + // Methods that will access private static methods of nestmates + + default void access_priv(TestJNI o) { + doCall(o.getClass(), METHOD); + } + default void access_priv(StaticNested o) { + doCall(o.getClass(), METHOD); + } + default void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(StaticIface.class, METHOD); + } + } + + static class StaticNested { + + private static void priv_static_invoke() { + System.out.println("StaticNested::priv_static_invoke"); + } + + // public constructor so we aren't relying on private access + public StaticNested() {} + + // Methods that will access private static methods of nestmates + + void access_priv(TestJNI o) { + doCall(o.getClass(), METHOD); + } + void access_priv(StaticNested o) { + doCall(o.getClass(), METHOD); + } + void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(StaticIface.class, METHOD); + } + } + + class InnerNested { + + // public constructor so we aren't relying on private access + public InnerNested() {} + + void access_priv(TestJNI o) { + doCall(o.getClass(), METHOD); + } + void access_priv(StaticNested o) { + doCall(o.getClass(), METHOD); + } + void access_priv(StaticIface o) { + // Can't use o.getClass() as the method is not in that class + doCall(StaticIface.class, METHOD); + } + } + + public static void main(String[] args) { + TestJNI o = new TestJNI(); + StaticNested s = new StaticNested(); + InnerNested i = o.new InnerNested(); + StaticIface intf = new StaticIface() {}; + + o.access_priv(new TestJNI()); + o.access_priv(s); + o.access_priv(intf); + + s.access_priv(o); + s.access_priv(new StaticNested()); + s.access_priv(intf); + + i.access_priv(o); + i.access_priv(s); + i.access_priv(intf); + + intf.access_priv(o); + intf.access_priv(s); + intf.access_priv(new StaticIface(){}); + } + + static void doCall(Class klass, String method) { + String definingClass = klass.getName(); + String desc = "Static invocation of " + definingClass + "." + method; + try { + NestmatesJNI.callStaticVoidVoid(definingClass, method); + System.out.println(desc + " - passed"); + } + catch (Throwable t) { + throw new Error(desc + ": Unexpected exception: " + t, t); + } + } +}