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 {}