changeset 50306:3234088eb2d2 nestmates

8191117: [Nestmates] Update JNI, JVM TI and JDI/JDWP to allow for nestmate access Reviewed-by: mainline RFR
author dholmes
date Mon, 28 May 2018 21:09:44 -0400
parents 41799b26a947
children 856c2c87fdf2
files test/hotspot/jtreg/runtime/Nestmates/NestmatesJNI.java test/hotspot/jtreg/runtime/Nestmates/libNestmatesJNI.c test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestJNI.java test/hotspot/jtreg/runtime/Nestmates/privateFields/TestJNI.java test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNI.java test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNIHierarchy.java test/hotspot/jtreg/runtime/Nestmates/privateStaticFields/TestJNI.java test/hotspot/jtreg/runtime/Nestmates/privateStaticMethods/TestJNI.java
diffstat 8 files changed, 1328 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/NestmatesJNI.java	Mon May 28 21:09:44 2018 -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, "<init>", 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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/libNestmatesJNI.c	Mon May 28 21:09:44 2018 -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 <jni.h>
+
+// 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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestJNI.java	Mon May 28 21:09:44 2018 -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> T newInstance(Class<T> klass) {
+        return newInstance(klass, null);
+    }
+
+    static <T> T newInstance(Class<T> 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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateFields/TestJNI.java	Mon May 28 21:09:44 2018 -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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNI.java	Mon May 28 21:09:44 2018 -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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNIHierarchy.java	Mon May 28 21:09:44 2018 -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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticFields/TestJNI.java	Mon May 28 21:09:44 2018 -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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticMethods/TestJNI.java	Mon May 28 21:09:44 2018 -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);
+        }
+    }
+}