1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8046171
  27  * @summary Test JNI access to private methods between nestmates and nest-host
  28  *          using different flavours of named nested types
  29  * @compile ../NestmatesJNI.java
  30  * @run main/othervm/native TestJNI
  31  * @run main/othervm/native -Xcheck:jni TestJNI
  32  */
  33 public class TestJNI {
  34 
  35     // Unlike reflection, the calling context is not relevant to JNI
  36     // calls, but we keep the same structure as the reflection tests.
  37 
  38     static final String METHOD = "priv_invoke";
  39 
  40     // Private method of nest-host for nestmates to access
  41     private void priv_invoke() {
  42         System.out.println("TestJNI::priv_invoke");
  43     }
  44 
  45     // public constructor so we aren't relying on private access
  46     public TestJNI() {}
  47 
  48     // Methods that will access private methods of nestmates
  49 
  50     void access_priv(TestJNI o) {
  51         doCall(o, o.getClass(), METHOD, true);
  52         doCall(o, o.getClass(), METHOD, false);
  53     }
  54     void access_priv(InnerNested o) {
  55         doCall(o, o.getClass(), METHOD, true);
  56         doCall(o, o.getClass(), METHOD, false);
  57     }
  58     void access_priv(StaticNested o) {
  59         doCall(o, o.getClass(), METHOD, true);
  60         doCall(o, o.getClass(), METHOD, false);
  61     }
  62     void access_priv(StaticIface o) {
  63         // Can't use o.getClass() as the method is not in that class
  64         doCall(o, StaticIface.class, METHOD, true);
  65         doCall(o, StaticIface.class, METHOD, false);
  66     }
  67 
  68     // The various nestmates
  69 
  70     static interface StaticIface {
  71 
  72         private void priv_invoke() {
  73             System.out.println("StaticIface::priv_invoke");
  74         }
  75 
  76         // Methods that will access private methods of nestmates
  77 
  78         default void access_priv(TestJNI o) {
  79             doCall(o, o.getClass(), METHOD, true);
  80             doCall(o, o.getClass(), METHOD, false);
  81         }
  82         default void access_priv(InnerNested o) {
  83             doCall(o, o.getClass(), METHOD, true);
  84             doCall(o, o.getClass(), METHOD, false);
  85         }
  86         default void access_priv(StaticNested o) {
  87             doCall(o, o.getClass(), METHOD, true);
  88             doCall(o, o.getClass(), METHOD, false);
  89         }
  90         default void access_priv(StaticIface o) {
  91             // Can't use o.getClass() as the method is not in that class
  92             doCall(o, StaticIface.class, METHOD, true);
  93             doCall(o, StaticIface.class, METHOD, false);
  94         }
  95     }
  96 
  97     static class StaticNested {
  98 
  99         private void priv_invoke() {
 100             System.out.println("StaticNested::priv_invoke");
 101         }
 102 
 103         // public constructor so we aren't relying on private access
 104         public StaticNested() {}
 105 
 106         // Methods that will access private methods of nestmates
 107 
 108         void access_priv(TestJNI o) {
 109             doCall(o, o.getClass(), METHOD, true);
 110             doCall(o, o.getClass(), METHOD, false);
 111         }
 112         void access_priv(InnerNested o) {
 113             doCall(o, o.getClass(), METHOD, true);
 114             doCall(o, o.getClass(), METHOD, false);
 115         }
 116         void access_priv(StaticNested o) {
 117             doCall(o, o.getClass(), METHOD, true);
 118             doCall(o, o.getClass(), METHOD, false);
 119         }
 120         void access_priv(StaticIface o) {
 121             // Can't use o.getClass() as the method is not in that class
 122             doCall(o, StaticIface.class, METHOD, true);
 123             doCall(o, StaticIface.class, METHOD, false);
 124         }
 125     }
 126 
 127     class InnerNested {
 128 
 129         private void priv_invoke() {
 130             System.out.println("InnerNested::priv_invoke");
 131         }
 132 
 133         // public constructor so we aren't relying on private access
 134         public InnerNested() {}
 135 
 136         void access_priv(TestJNI o) {
 137             doCall(o, o.getClass(), METHOD, true);
 138             doCall(o, o.getClass(), METHOD, false);
 139         }
 140         void access_priv(InnerNested o) {
 141             doCall(o, o.getClass(), METHOD, true);
 142             doCall(o, o.getClass(), METHOD, false);
 143         }
 144         void access_priv(StaticNested o) {
 145             doCall(o, o.getClass(), METHOD, true);
 146             doCall(o, o.getClass(), METHOD, false);
 147         }
 148         void access_priv(StaticIface o) {
 149             // Can't use o.getClass() as the method is not in that class
 150             doCall(o, StaticIface.class, METHOD, true);
 151             doCall(o, StaticIface.class, METHOD, false);
 152         }
 153     }
 154 
 155     public static void main(String[] args) {
 156         TestJNI o = new TestJNI();
 157         StaticNested s = new StaticNested();
 158         InnerNested i = o.new InnerNested();
 159         StaticIface intf = new StaticIface() {};
 160 
 161         o.access_priv(new TestJNI());
 162         o.access_priv(i);
 163         o.access_priv(s);
 164         o.access_priv(intf);
 165 
 166         s.access_priv(o);
 167         s.access_priv(i);
 168         s.access_priv(new StaticNested());
 169         s.access_priv(intf);
 170 
 171         i.access_priv(o);
 172         i.access_priv(o.new InnerNested());
 173         i.access_priv(s);
 174         i.access_priv(intf);
 175 
 176         intf.access_priv(o);
 177         intf.access_priv(i);
 178         intf.access_priv(s);
 179         intf.access_priv(new StaticIface(){});
 180     }
 181 
 182 
 183     static void doCall(Object target, Class<?> klass, String method,
 184                        boolean virtual) {
 185         String definingClass = klass.getName();
 186         String desc = (virtual ? "Virtual" : "Nonvirtual") + " Invocation of " +
 187                        definingClass + "." + method + " on instance of class " +
 188                        target.getClass().getName();
 189         try {
 190             NestmatesJNI.callVoidVoid(target, definingClass, method, virtual);
 191             System.out.println(desc + " - passed");
 192         }
 193         catch (Throwable t) {
 194             throw new Error(desc + ": Unexpected exception: " + t, t);
 195         }
 196     }
 197 }