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 access to private methods between nestmates where there 28 * is an inheritance hierarchy and we invoke private methods that 29 * exist in specific classes in the hierarchy. 30 * @compile ../NestmatesJNI.java 31 * @run main/othervm/native TestJNIHierarchy 32 * @run main/othervm/native -Xcheck:jni TestJNIHierarchy 33 */ 34 35 public class TestJNIHierarchy { 36 37 // Unlike reflection, the calling context is not relevant to JNI 38 // calls, but we keep the same structure as the reflection tests. 39 40 static final String METHOD = "priv_invoke"; 41 42 static class NestedA extends ExternalSuper { 43 static final String ID = "NestedA::priv_invoke"; 44 private String priv_invoke() { 45 return ID; 46 } 47 static void checkA(NestedA a) { 48 String res = NestmatesJNI.callStringVoid(a, 49 NestedA.class.getName(), 50 METHOD, 51 true); 52 verifyEquals(res, NestedA.ID); 53 res = NestmatesJNI.callStringVoid(a, 54 NestedA.class.getName(), 55 METHOD, 56 false); 57 verifyEquals(res, NestedA.ID); 58 } 59 } 60 61 static class NestedB extends NestedA { 62 static final String ID = "NestedB::priv_invoke"; 63 private String priv_invoke() { 64 return ID; 65 } 66 static void checkA(NestedA a) { 67 String res = NestmatesJNI.callStringVoid(a, 68 NestedA.class.getName(), 69 METHOD, 70 true); 71 verifyEquals(res, NestedA.ID); 72 73 res = NestmatesJNI.callStringVoid(a, 74 NestedA.class.getName(), 75 METHOD, 76 false); 77 verifyEquals(res, NestedA.ID); 78 } 79 } 80 81 static class NestedC extends NestedB { 82 static final String ID = "NestedC::priv_invoke"; 83 private String priv_invoke() { 84 return ID; 85 } 86 static void checkA(NestedA a) { 87 String res = NestmatesJNI.callStringVoid(a, 88 NestedA.class.getName(), 89 METHOD, 90 true); 91 verifyEquals(res, NestedA.ID); 92 } 93 } 94 95 static void checkA(NestedA a) { 96 String res = NestmatesJNI.callStringVoid(a, 97 NestedA.class.getName(), 98 METHOD, 99 true); 100 verifyEquals(res, NestedA.ID); 101 102 res = NestmatesJNI.callStringVoid(a, 103 NestedA.class.getName(), 104 METHOD, 105 false); 106 verifyEquals(res, NestedA.ID); 107 } 108 109 static void checkB(NestedB b) { 110 String res = NestmatesJNI.callStringVoid(b, 111 NestedB.class.getName(), 112 METHOD, 113 true); 114 verifyEquals(res, NestedB.ID); 115 116 res = NestmatesJNI.callStringVoid(b, 117 NestedB.class.getName(), 118 METHOD, 119 false); 120 verifyEquals(res, NestedB.ID); 121 122 } 123 124 static void checkC(NestedC c) { 125 String res = NestmatesJNI.callStringVoid(c, 126 NestedC.class.getName(), 127 METHOD, 128 true); 129 verifyEquals(res, NestedC.ID); 130 131 res = NestmatesJNI.callStringVoid(c, 132 NestedC.class.getName(), 133 METHOD, 134 false); 135 verifyEquals(res, NestedC.ID); 136 } 137 138 139 // Access to private members of classes outside the nest is 140 // not permitted in general, but JNI ignores all access checks. 141 142 static void checkExternalSuper(ExternalSuper s) { 143 String res = NestmatesJNI.callStringVoid(s, 144 ExternalSuper.class.getName(), 145 METHOD, 146 true); 147 verifyEquals(res, ExternalSuper.ID); 148 149 res = NestmatesJNI.callStringVoid(s, 150 ExternalSuper.class.getName(), 151 METHOD, 152 false); 153 verifyEquals(res, ExternalSuper.ID); 154 } 155 156 static void checkExternalSub(ExternalSub s) { 157 String res = NestmatesJNI.callStringVoid(s, 158 ExternalSub.class.getName(), 159 METHOD, 160 true); 161 verifyEquals(res, ExternalSub.ID); 162 163 res = NestmatesJNI.callStringVoid(s, 164 ExternalSub.class.getName(), 165 METHOD, 166 false); 167 verifyEquals(res, ExternalSub.ID); 168 } 169 170 static void verifyEquals(String actual, String expected) { 171 if (!actual.equals(expected)) { 172 throw new Error("Expected " + expected + " but got " + actual); 173 } 174 System.out.println("Check passed for " + expected); 175 } 176 177 public static void main(String[] args) { 178 NestedA a = new NestedA(); 179 NestedB b = new NestedB(); 180 NestedC c = new NestedC(); 181 ExternalSub sub = new ExternalSub(); 182 ExternalSuper sup = new ExternalSuper(); 183 184 checkExternalSuper(sup); 185 checkExternalSuper(a); 186 checkExternalSuper(b); 187 checkExternalSuper(c); 188 checkExternalSuper(sub); 189 190 checkA(a); 191 checkA(b); 192 checkA(c); 193 checkA(sub); 194 195 NestedA.checkA(a); 196 NestedA.checkA(b); 197 NestedA.checkA(c); 198 NestedA.checkA(sub); 199 200 NestedB.checkA(a); 201 NestedB.checkA(b); 202 NestedB.checkA(c); 203 NestedB.checkA(sub); 204 205 NestedC.checkA(a); 206 NestedC.checkA(b); 207 NestedC.checkA(c); 208 NestedC.checkA(sub); 209 210 checkB(b); 211 checkB(c); 212 checkB(sub); 213 214 checkC(c); 215 checkC(sub); 216 217 checkExternalSub(sub); 218 } 219 } 220 221 // Classes that are not part of the nest. 222 // Being non-public allows us to declare them in this file. 223 224 class ExternalSuper { 225 static final String ID = "ExternalSuper::priv_invoke"; 226 private String priv_invoke() { 227 return ID; 228 } 229 } 230 231 232 class ExternalSub extends TestJNIHierarchy.NestedC { 233 static final String ID = "ExternalSub::priv_invoke"; 234 private String priv_invoke() { 235 return ID; 236 } 237 }