1 /* 2 * Copyright (c) 2023, 2024, 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 /* 26 * @test 27 * @requires vm.cds 28 * @summary Test for verification of classes that are preloaded 29 * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds 30 * @build GoodOldClass BadOldClass BadOldClass2 BadNewClass BadNewClass2 31 * @build PreloadedClassesVerification 32 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar jdk.test.whitebox.WhiteBox 33 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app1.jar 34 * PreloadedClassesVerificationApp 35 * Unlinked UnlinkedSuper 36 * BadOldClass 37 * BadOldClass2 38 * BadNewClass 39 * BadNewClass2 40 * GoodOldClass Vehicle Car 41 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app2.jar 42 * UnlinkedSub 43 * Foo NotFoo 44 * @run driver PreloadedClassesVerification 45 */ 46 47 import java.io.File; 48 import jdk.test.lib.helpers.ClassFileInstaller; 49 import jdk.test.whitebox.WhiteBox; 50 51 public class PreloadedClassesVerification { 52 static final String app1Jar = ClassFileInstaller.getJarPath("app1.jar"); 53 static final String app2Jar = ClassFileInstaller.getJarPath("app2.jar"); 54 static final String wbJar = TestCommon.getTestJar("WhiteBox.jar"); 55 static final String bootAppendWhiteBox = "-Xbootclasspath/a:" + wbJar; 56 static final String mainClass = PreloadedClassesVerificationApp.class.getName(); 57 58 public static void main(String[] args) throws Exception { 59 // Dump without app2.jar so: 60 // - Unlinked can be resolved, but UnlinkedSuper UnlinkedSub cannot be resolved, 61 // so Unlinked cannot be verified at dump time. 62 // - BadOldClass2 can be resolved, but Foo and NotFoo cannot be resolved, 63 // so BadOldClass2 cannot be verified at dump time. 64 // - BadNewClass2 can be resolved, but Foo and NotFoo cannot be resolved, 65 // so BadNewClass2 cannot be verified at dump time. 66 TestCommon.testDump(app1Jar, TestCommon.list("Unlinked", 67 "BadOldClass", 68 "BadOldClass2", 69 "BadNewClass", 70 "BadNewClass2", 71 "GoodOldClass"), 72 bootAppendWhiteBox, 73 "-XX:+PreloadSharedClasses", 74 "-Xlog:cds+class=debug"); 75 76 TestCommon.run("-cp", app1Jar + File.pathSeparator + app2Jar, 77 "-XX:+UnlockDiagnosticVMOptions", 78 "-XX:+WhiteBoxAPI", 79 bootAppendWhiteBox, 80 "PreloadedClassesVerificationApp") 81 .assertNormalExit(); 82 } 83 } 84 85 class PreloadedClassesVerificationApp { 86 static WhiteBox wb = WhiteBox.getWhiteBox(); 87 static ClassLoader classLoader = PreloadedClassesVerificationApp.class.getClassLoader(); 88 89 public static void main(String[] args) throws Exception { 90 assertNotShared(UnlinkedSub.class); 91 assertShared(UnlinkedSuper.class); 92 assertShared(Unlinked.class); 93 assertNotShared(Foo.class); 94 assertNotShared(NotFoo.class); 95 String s = Unlinked.doit(); 96 if (!s.equals("heyhey")) { 97 throw new RuntimeException("Unlinked.doit() returns wrong result: " + s); 98 } 99 100 Class cls_BadOldClass = Class.forName("BadOldClass", false, classLoader); 101 assertShared(cls_BadOldClass); 102 try { 103 cls_BadOldClass.newInstance(); 104 throw new RuntimeException("BadOldClass cannot be verified"); 105 } catch (VerifyError expected) {} 106 107 Class cls_BadOldClass2 = Class.forName("BadOldClass2", false, classLoader); 108 assertShared(cls_BadOldClass2); 109 try { 110 cls_BadOldClass2.newInstance(); 111 throw new RuntimeException("BadOldClass2 cannot be verified"); 112 } catch (VerifyError expected) {} 113 114 Class cls_BadNewClass = Class.forName("BadNewClass", false, classLoader); 115 assertShared(cls_BadNewClass); 116 try { 117 cls_BadNewClass.newInstance(); 118 throw new RuntimeException("BadNewClass cannot be verified"); 119 } catch (VerifyError expected) {} 120 121 Class cls_BadNewClass2 = Class.forName("BadNewClass2", false, classLoader); 122 assertShared(cls_BadNewClass2); 123 try { 124 cls_BadNewClass2.newInstance(); 125 throw new RuntimeException("BadNewClass2 cannot be verified"); 126 } catch (VerifyError expected) {} 127 128 129 // Although Vehicle and Car are not specified in the classlist, they are archived as 130 // they were used during dumptime verification of GoodOldClass 131 assertShared(GoodOldClass.class); 132 assertShared(Vehicle.class); 133 assertShared(Car.class); 134 135 GoodOldClass.doit(); // Should not fail 136 } 137 138 static void assertShared(Class c) { 139 if (!wb.isSharedClass(c)) { 140 throw new RuntimeException("wb.isSharedClass(" + c.getName() + ") should be true"); 141 } 142 } 143 144 static void assertNotShared(Class c) { 145 if (wb.isSharedClass(c)) { 146 throw new RuntimeException("wb.isSharedClass(" + c.getName() + ") should be false"); 147 } 148 } 149 } 150 151 152 class Unlinked { 153 static String doit() { 154 UnlinkedSuper sup = new UnlinkedSub(); 155 return sup.doit(); 156 } 157 } 158 159 abstract class UnlinkedSuper { 160 abstract String doit(); 161 } 162 163 class UnlinkedSub extends UnlinkedSuper { 164 String doit() { 165 return "heyhey"; 166 } 167 } 168 169 class Foo {} 170 class NotFoo {} 171 172 class Vehicle {} 173 class Car extends Vehicle {}