1 /* 2 * Copyright (c) 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 * @library /test/lib 27 * @modules java.compiler 28 * @build jdk.test.lib.compiler.CompilerUtils 29 * jdk.test.lib.Utils * 30 * @run shell ../MakeJAR3.sh HiddenClassAgent 'Can-Retransform-Classes: true' 31 * @run main/othervm/native -javaagent:HiddenClassAgent.jar HiddenClassApp 32 */ 33 34 import java.lang.instrument.*; 35 36 /* Test that Instrumentation getAllLoadedClasses includes 37 * hidden classes but getInitiatedClasses does not. 38 * Check that all hidden classes are non-retransformable. 39 */ 40 public class HiddenClassAgent extends Thread { 41 private static volatile boolean completed = false; 42 private static volatile boolean failed = false; 43 private static volatile boolean hiddenClassLoaded = false; 44 45 private static Instrumentation instr = null; 46 private static Object monitor = new Object(); 47 48 static void log(String str) { System.err.println(str); } 49 public static boolean failed() { return failed; } 50 51 public static 52 boolean checkWaitForCompleteness() { 53 try { 54 synchronized (monitor) { 55 while (!completed) { 56 monitor.wait(100); 57 } 58 } 59 } catch (InterruptedException ex) { 60 ex.printStackTrace(); 61 log("HiddenClassAgent: waitCheckForCompletness: Caught InterruptedException: " + ex); 62 } 63 return completed; 64 } 65 66 public static 67 void setHiddenClassLoaded() { 68 synchronized (monitor) { 69 hiddenClassLoaded = true; 70 monitor.notifyAll(); 71 } 72 } 73 74 private static 75 void waitForHiddenClassLoad() { 76 try { 77 synchronized (monitor) { 78 while (!hiddenClassLoaded) { 79 monitor.wait(100); 80 } 81 } 82 } catch (InterruptedException ex) { 83 ex.printStackTrace(); 84 log("HiddenClassAgent: waitForHiddenClassLoad: Caught InterruptedException: " + ex); 85 } 86 } 87 88 private static 89 ClassLoader testGetAllLoadedClasses() { 90 boolean hiddenClassFound = false; 91 ClassLoader loader = null; 92 Class<?>[] classes = instr.getAllLoadedClasses(); 93 94 for (int i = 0; i < classes.length; i++) { 95 Class klass = classes[i]; 96 97 if (!klass.isHiddenClass() || !klass.getName().contains("HiddenClass/")) { 98 continue; 99 } 100 log("HiddenClassAgent: getAllLoadedClasses returned hidden class: " + klass); 101 hiddenClassFound = true; 102 loader = klass.getClassLoader(); 103 log("HiddenClassAgent: class loader of hidden class: " + loader); 104 105 try { 106 instr.retransformClasses(klass); 107 log("HiddenClassAgent: FAIL: hidden class is retransformable: " + klass); 108 failed = true; 109 } catch (UnmodifiableClassException e) { 110 log("HiddenClassAgent: Got expected UnmodifiableClassException for class: " + klass); 111 } catch (Throwable e) { 112 log("HiddenClassAgent: FAIL: unexpected throwable in hidden class retransform: " + klass); 113 log("HiddenClassAgent: got Throwable" + e); 114 failed = true; 115 } 116 } 117 if (!hiddenClassFound) { 118 log("HiddenClassAgent: FAIL: a hidden class is not found in getAllLoadedClasses list"); 119 failed = true; 120 } 121 return loader; 122 } 123 124 private static 125 void testGetInitiatedClasses(ClassLoader loader) { 126 Class<?>[] classes = instr.getInitiatedClasses(loader); 127 for (int i = 0; i < classes.length; i++) { 128 Class klass = classes[i]; 129 130 if (klass.isHiddenClass()) { 131 log("HiddenClassAgent: FAIL: getInitiatedClasses returned hidden class: " + klass); 132 failed = true; 133 return; 134 } 135 } 136 log("HiddenClassAgent: getInitiatedClasses returned no hidden classes as expected"); 137 } 138 139 public static void 140 premain(String agentArgs, Instrumentation instrumentation) { 141 instr = instrumentation; 142 Thread agentThread = new HiddenClassAgent(); 143 agentThread.start(); 144 } 145 146 public void run () { 147 log("HiddenClassAgent: started"); 148 waitForHiddenClassLoad(); 149 150 // Test getAllLoadedClasses 151 ClassLoader loader = testGetAllLoadedClasses(); 152 153 // Test getInitiatedClasses 154 testGetInitiatedClasses(null); 155 if (loader != null) { 156 testGetInitiatedClasses(loader); 157 } 158 159 synchronized (monitor) { 160 completed = true; 161 monitor.notifyAll(); 162 } 163 log("HiddenClassAgent: finished"); 164 } 165 }