1 /* 2 * Copyright (c) 2015, 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 8140450 27 * @summary Basic test for StackWalker.getCallerClass() 28 * @run main/othervm -XX:-MemberNameInStackFrame GetCallerClassTest 29 * @run main/othervm -XX:+MemberNameInStackFrame GetCallerClassTest 30 * @run main/othervm GetCallerClassTest sm 31 */ 32 33 import static java.lang.StackWalker.Option.*; 34 import java.lang.invoke.MethodHandle; 35 import java.lang.invoke.MethodHandles; 36 import java.lang.invoke.MethodType; 37 import java.lang.reflect.InvocationTargetException; 38 import java.lang.reflect.Method; 39 import java.security.Permission; 40 import java.security.PermissionCollection; 41 import java.security.Permissions; 42 import java.security.Policy; 43 import java.security.ProtectionDomain; 44 import java.util.Arrays; 45 import java.util.List; 46 47 public class GetCallerClassTest { 48 private final StackWalker walker; 49 private final boolean expectUOE; 50 51 public GetCallerClassTest(StackWalker sw, boolean expect) { 52 this.walker = sw; 53 this.expectUOE = expect; 54 } 55 public static void main(String... args) throws Exception { 56 if (args.length > 0 && args[0].equals("sm")) { 57 PermissionCollection perms = new Permissions(); 58 perms.add(new StackFramePermission("retainClassReference")); 59 Policy.setPolicy(new Policy() { 60 @Override 61 public boolean implies(ProtectionDomain domain, Permission p) { 62 return perms.implies(p); 63 } 64 }); 65 System.setSecurityManager(new SecurityManager()); 66 } 67 new GetCallerClassTest(StackWalker.getInstance(), true).test(); 68 new GetCallerClassTest(StackWalker.getInstance(RETAIN_CLASS_REFERENCE), false).test(); 69 } 70 71 public void test() { 72 new TopLevelCaller().run(); 73 new Nested().createNestedCaller().run(); 74 new InnerClassCaller().run(); 75 new ReflectionTest().run(); 76 77 List<Thread> threads = Arrays.asList( 78 new Thread(new TopLevelCaller()), 79 new Thread(new Nested().createNestedCaller()), 80 new Thread(new InnerClassCaller()), 81 new Thread(new ReflectionTest()) 82 ); 83 threads.stream().forEach(Thread::start); 84 threads.stream().forEach(t -> { 85 try { 86 t.join(); 87 } catch (InterruptedException e) { 88 throw new RuntimeException(e); 89 } 90 }); 91 } 92 93 public static void staticGetCallerClass(StackWalker stackWalker, 94 Class<?> expected, 95 boolean expectUOE) { 96 try { 97 Class<?> c = stackWalker.getCallerClass(); 98 assertEquals(c, expected); 99 if (expectUOE) { // Should have thrown 100 throw new RuntimeException("Didn't get expected exception"); 101 } 102 } catch (RuntimeException e) { // also catches UOE 103 if (expectUOE && causeIsUOE(e)) { 104 return; /* expected */ 105 } 106 System.err.println("Unexpected exception:"); 107 throw e; 108 } 109 } 110 111 public static void reflectiveGetCallerClass(StackWalker stackWalker, 112 Class<?> expected, 113 boolean expectUOE) { 114 try { 115 Method m = StackWalker.class.getMethod("getCallerClass"); 116 Class<?> c = (Class<?>) m.invoke(stackWalker); 117 assertEquals(c, expected); 118 if (expectUOE) { // Should have thrown 119 throw new RuntimeException("Didn't get expected exception"); 120 } 121 } catch (Throwable e) { 122 if (expectUOE && causeIsUOE(e)) { 123 return; /* expected */ 124 } 125 System.err.println("Unexpected exception:"); 126 throw new RuntimeException(e); 127 } 128 } 129 130 public static void methodHandleGetCallerClass(StackWalker stackWalker, 131 Class<?> expected, 132 boolean expectUOE) { 133 MethodHandles.Lookup lookup = MethodHandles.lookup(); 134 try { 135 MethodHandle mh = lookup.findVirtual(StackWalker.class, "getCallerClass", 136 MethodType.methodType(Class.class)); 137 Class<?> c = (Class<?>) mh.invokeExact(stackWalker); 138 assertEquals(c, expected); 139 if (expectUOE) { // Should have thrown 140 throw new RuntimeException("Didn't get expected exception"); 141 } 142 } catch (Throwable e) { 143 if (expectUOE && causeIsUOE(e)) { 144 return; /* expected */ 145 } 146 System.err.println("Unexpected exception:"); 147 throw new RuntimeException(e); 148 } 149 } 150 151 public static void assertEquals(Class<?> c, Class<?> expected) { 152 if (expected != c) { 153 throw new RuntimeException(c + " != " + expected); 154 } 155 } 156 157 /** Is there an UnsupportedOperationException in there? */ 158 public static boolean causeIsUOE(Throwable t) { 159 while (t != null) { 160 if (t instanceof UnsupportedOperationException) { 161 return true; 162 } 163 t = t.getCause(); 164 } 165 return false; 166 } 167 168 class TopLevelCaller implements Runnable { 169 public void run() { 170 GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE); 171 GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE); 172 GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE); 173 } 174 } 175 176 class Nested { 177 NestedClassCaller createNestedCaller() { return new NestedClassCaller(); } 178 class NestedClassCaller implements Runnable { 179 public void run() { 180 GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE); 181 GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE); 182 GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE); 183 } 184 } 185 } 186 187 class InnerClassCaller implements Runnable { 188 public void run() { 189 new Inner().test(); 190 } 191 class Inner { 192 void test() { 193 GetCallerClassTest.staticGetCallerClass(walker, this.getClass(), expectUOE); 194 GetCallerClassTest.reflectiveGetCallerClass(walker, this.getClass(), expectUOE); 195 GetCallerClassTest.methodHandleGetCallerClass(walker, this.getClass(), expectUOE); 196 } 197 } 198 } 199 200 class ReflectionTest implements Runnable { 201 final MethodType methodType = 202 MethodType.methodType(void.class, StackWalker.class, Class.class, boolean.class); 203 204 public void run() { 205 callMethodHandle(); 206 callMethodHandleRefl(); 207 callMethodInvoke(); 208 callMethodInvokeRefl(); 209 } 210 void callMethodHandle() { 211 MethodHandles.Lookup lookup = MethodHandles.publicLookup(); 212 try { 213 MethodHandle mh = lookup.findStatic(GetCallerClassTest.class, 214 "staticGetCallerClass", 215 methodType); 216 mh.invokeExact(walker, ReflectionTest.class, expectUOE); 217 } catch (Throwable e) { 218 throw new RuntimeException(e); 219 } 220 } 221 void callMethodHandleRefl() { 222 MethodHandles.Lookup lookup = MethodHandles.publicLookup(); 223 try { 224 MethodHandle mh = lookup.findStatic(GetCallerClassTest.class, 225 "reflectiveGetCallerClass", 226 methodType); 227 mh.invokeExact(walker, ReflectionTest.class, expectUOE); 228 } catch (Throwable e) { 229 throw new RuntimeException(e); 230 } 231 } 232 void callMethodInvoke() { 233 try { 234 Method m = GetCallerClassTest.class.getMethod("staticGetCallerClass", 235 StackWalker.class, Class.class, boolean.class); 236 m.invoke(null, walker, ReflectionTest.class, expectUOE); 237 } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) { 238 throw new RuntimeException(e); 239 } 240 } 241 void callMethodInvokeRefl() { 242 try { 243 Method m = GetCallerClassTest.class.getMethod("reflectiveGetCallerClass", 244 StackWalker.class, Class.class, boolean.class); 245 m.invoke(null, walker, ReflectionTest.class, expectUOE); 246 } catch (UnsupportedOperationException e) { 247 throw e; 248 } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) { 249 throw new RuntimeException(e); 250 } 251 } 252 } 253 }