1 /* 2 * Copyright (c) 2017, 2020, 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 the new nestmate reflection API 28 * @compile TestReflectionAPI.java 29 * PackagedNestHost.java 30 * PackagedNestHost2.java 31 * SampleNest.java 32 * Hosts.java 33 * InvalidNestHost.java 34 * 35 * @compile MemberNoHost.jcod 36 * MemberMissingHost.jcod 37 * MemberNotInstanceHost.jcod 38 * MemberNotOurHost.jcod 39 * MemberMalformedHost.jcod 40 * MalformedHost.jcod 41 * PackagedNestHost.jcod 42 * PackagedNestHost2Member.jcod 43 * PackagedNestHostMember.jcod 44 * HostOfMemberNoHost.jcod 45 * HostOfMemberMissingHost.jcod 46 * HostOfMemberNotInstanceHost.jcod 47 * HostOfMemberNotOurHost.jcod 48 * HostOfMemberMalformedHost.jcod 49 * HostWithSelfMember.jcod 50 * HostWithDuplicateMembers.jcod 51 * 52 * @run main/othervm TestReflectionAPI 53 * @run main/othervm/java.security.policy=empty.policy TestReflectionAPI 54 */ 55 56 // We need a nest member class that is invalid for each of the possible reasons, 57 // plus we need some external classes to test other failure modes. 58 // For each nested class below there is a corresponding .jcod file which breaks one 59 // of the rules regarding nest membership. For the package related tests we have 60 // additional PackageNestHost*.java sources. 61 // For testing getNestMembers we need an external host class that has a nested class 62 // which we can form a jcod file from such that we get all the expected failure modes. 63 // Note that all the .java files must be compiled in the same step, while all 64 // .jcod files must be compiled in a later step. 65 66 import java.util.Arrays; 67 import java.util.Comparator; 68 import java.util.HashSet; 69 70 public class TestReflectionAPI { 71 72 // Valid nest member 73 static class Member {} 74 75 // Missing NestHost attribute 76 static class MemberNoHost {} 77 78 // Missing NestHost class 79 static class MemberMissingHost {} 80 81 // Invalid NestHost class (not instance class) 82 static class MemberNotInstanceHost { 83 Object[] oa; // create CP entry to use in jcod change 84 } 85 86 // Valid but different NestHost class 87 static class MemberNotOurHost {} 88 89 // Malformed NestHost class 90 static class MemberMalformedHost {} 91 92 public static void main(String[] args) throws Throwable { 93 // run tests twice so that failure reasons are 94 // seen to remain the same 95 for (int i = 0; i < 2; i++) { 96 test_getNestHost(); 97 test_isNestmateOf(); 98 test_getNestMembers(); 99 } 100 } 101 102 static void test_getNestHost() { 103 Class<?> host = TestReflectionAPI.class; 104 105 // sampling of "good" checks 106 107 checkHost(host, host); 108 checkHost(Member.class, host); 109 Runnable r = new Runnable() { public void run() {}}; 110 checkHost(r.getClass(), host); 111 112 // all the "bad" classes should report themselves as their 113 // own nest host - no exceptions should be thrown 114 Class<?>[] allClasses = host.getDeclaredClasses(); 115 for (Class<?> c : allClasses) { 116 if (c == Member.class) 117 continue; 118 checkHost(c, c); 119 } 120 checkHost(P1.PackagedNestHost.Member.class, 121 P1.PackagedNestHost.Member.class); 122 checkHost(P2.PackagedNestHost2.Member.class, 123 P2.PackagedNestHost2.Member.class); 124 125 // test some 'special' classes 126 checkHost(int.class, int.class); // primitive 127 checkHost(Object[].class, Object[].class); // array 128 checkHost(Thread.State.class, Thread.class); // enum 129 checkHost(java.lang.annotation.Documented.class, // annotation 130 java.lang.annotation.Documented.class); 131 } 132 133 static void test_isNestmateOf() { 134 Class<?> host = TestReflectionAPI.class; 135 checkNestmates(host, host, true); 136 checkNestmates(Member.class, host, true); 137 Runnable r = new Runnable() { public void run() {}}; 138 checkNestmates(r.getClass(), host, true); 139 140 // all the "bad" classes should report themselves as their 141 // own nest host - no exceptions should be thrown - so not 142 // nestmates 143 Class<?>[] allClasses = host.getDeclaredClasses(); 144 for (Class<?> c : allClasses) { 145 if (c == Member.class) 146 continue; 147 checkNestmates(host, c, false); 148 } 149 150 // 'special' classes 151 checkNestmates(int.class, int.class, true); // primitive 152 checkNestmates(int.class, long.class, false); // primitive 153 checkNestmates(Object[].class, Object[].class, true); // array 154 checkNestmates(Object[].class, int[].class, false); // array 155 checkNestmates(Thread.State.class, Thread.class, true); // enum 156 checkNestmates(java.lang.annotation.Documented.class, // annotation 157 java.lang.annotation.Documented.class, true); 158 } 159 160 static void test_getNestMembers() { 161 // Sampling of "good" checks 162 Class<?>[] good = { Object.class, Object[].class, int.class}; 163 checkSingletonNests(good); 164 165 // More thorough correctness check 166 checkNest(SampleNest.class, SampleNest.nestedTypes(), false); 167 168 // Special cases - legal but not produced by javac 169 checkNest(HostWithSelfMember.class, 170 new Class<?>[] { HostWithSelfMember.class, 171 HostWithSelfMember.Member.class }, 172 true); 173 checkNest(HostWithDuplicateMembers.class, 174 new Class<?>[] { HostWithDuplicateMembers.class, 175 HostWithDuplicateMembers.Member1.class, 176 HostWithDuplicateMembers.Member2.class }, 177 true); 178 179 // Hosts with only "bad" members 180 Class<?>[] bad = { 181 HostOfMemberNoHost.class, 182 HostOfMemberMissingHost.class, 183 HostOfMemberNotOurHost.class, 184 HostOfMemberNotInstanceHost.class, 185 HostOfMemberMalformedHost.class, 186 }; 187 checkSingletonNests(bad); 188 } 189 190 static void checkHost(Class<?> target, Class<?> expected) { 191 System.out.println("Checking nest host of " + target.getName()); 192 Class<?> host = target.getNestHost(); 193 if (host != expected) 194 throw new Error("Class " + target.getName() + 195 " has nest host " + host.getName() + 196 " but expected " + expected.getName()); 197 } 198 199 static void checkNestmates(Class<?> a, Class<?> b, boolean mates) { 200 System.out.println("Checking if " + a.getName() + 201 " isNestmateOf " + b.getName()); 202 203 if (a.isNestmateOf(b) != mates) 204 throw new Error("Class " + a.getName() + " is " + 205 (mates ? "not " : "") + 206 "a nestmate of " + b.getName() + " but should " + 207 (mates ? "" : "not ") + "be"); 208 } 209 210 static Comparator<Class<?>> cmp = Comparator.comparing(Class::getName); 211 212 static void checkNest(Class<?> host, Class<?>[] unsortedTypes, boolean expectDups) { 213 Class<?>[] members = host.getNestMembers(); 214 Arrays.sort(members, cmp); 215 Class<?>[] nestedTypes = unsortedTypes.clone(); 216 Arrays.sort(nestedTypes, cmp); 217 printMembers(host, members); 218 printDeclared(host, nestedTypes); 219 if (!Arrays.equals(members, nestedTypes)) { 220 if (!expectDups) { 221 throw new Error("Class " + host.getName() + " has different members " + 222 "compared to declared classes"); 223 } 224 else { 225 // get rid of duplicates 226 Class<?>[] memberSet = 227 Arrays.stream(members).sorted(cmp).distinct().toArray(Class<?>[]::new); 228 if (!Arrays.equals(memberSet, nestedTypes)) { 229 throw new Error("Class " + host.getName() + " has different members " + 230 "compared to declared classes, even after duplicate removal"); 231 } 232 } 233 } 234 // verify all the relationships that must hold for nest members 235 for (Class<?> a : members) { 236 checkHost(a, host); 237 checkNestmates(a, host, true); 238 Class<?>[] aMembers = a.getNestMembers(); 239 if (aMembers[0] != host) { 240 throw new Error("Class " + a.getName() + " getNestMembers()[0] = " + 241 aMembers[0].getName() + " not " + host.getName()); 242 243 } 244 Arrays.sort(aMembers, cmp); 245 if (!Arrays.equals(members, aMembers)) { 246 throw new Error("Class " + a.getName() + " has different members " + 247 "compared to host " + host.getName()); 248 } 249 for (Class<?> b : members) { 250 checkNestmates(a, b, true); 251 } 252 } 253 } 254 255 static void checkSingletonNests(Class<?>[] classes) { 256 for (Class<?> host : classes) { 257 Class<?>[] members = host.getNestMembers(); 258 if (members.length != 1) { 259 printMembers(host, members); 260 throw new Error("Class " + host.getName() + " lists " + members.length 261 + " members instead of 1 (itself)"); 262 } 263 if (members[0] != host) { 264 printMembers(host, members); 265 throw new Error("Class " + host.getName() + " lists " + 266 members[0].getName() + " as member instead of itself"); 267 } 268 } 269 } 270 271 static void printMembers(Class<?> host, Class<?>[] members) { 272 System.out.println("Class " + host.getName() + " has members: "); 273 for (Class<?> c : members) { 274 System.out.println(" - " + c.getName()); 275 } 276 } 277 278 static void printDeclared(Class<?> host, Class<?>[] declared) { 279 System.out.println("Class " + host.getName() + " has declared types: "); 280 for (Class<?> c : declared) { 281 System.out.println(" - " + c.getName()); 282 } 283 } 284 285 }