1 /*
  2  * Copyright (c) 2023, 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 PreloadedClassVerification
 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  *                 PreloadedClassVerificationApp
 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 PreloadedClassVerification
 45  */
 46 
 47 import java.io.File;
 48 import jdk.test.lib.helpers.ClassFileInstaller;
 49 import jdk.test.whitebox.WhiteBox;
 50 
 51 public class PreloadedClassVerification {
 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 = PreloadedClassVerificationApp.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                             "-Xlog:cds+class=debug");
 74 
 75         TestCommon.run("-cp", app1Jar + File.pathSeparator + app2Jar,
 76                        "-XX:+UnlockDiagnosticVMOptions",
 77                        "-XX:+WhiteBoxAPI",
 78                        bootAppendWhiteBox,
 79                        "PreloadedClassVerificationApp")
 80             .assertNormalExit();
 81     }
 82 }
 83 
 84 class PreloadedClassVerificationApp {
 85     static WhiteBox wb = WhiteBox.getWhiteBox();
 86     static ClassLoader classLoader = PreloadedClassVerificationApp.class.getClassLoader();
 87 
 88     public static void main(String[] args) throws Exception {
 89         assertNotShared(UnlinkedSub.class);
 90         assertShared(UnlinkedSuper.class);
 91         assertShared(Unlinked.class);
 92         assertNotShared(Foo.class);
 93         assertNotShared(NotFoo.class);
 94         String s = Unlinked.doit();
 95         if (!s.equals("heyhey")) {
 96             throw new RuntimeException("Unlinked.doit() returns wrong result: " + s);
 97         }
 98 
 99         Class cls_BadOldClass = Class.forName("BadOldClass", false, classLoader);
100         assertShared(cls_BadOldClass);
101         try {
102             cls_BadOldClass.newInstance();
103             throw new RuntimeException("BadOldClass cannot be verified");
104         } catch (VerifyError expected) {}
105 
106         Class cls_BadOldClass2 = Class.forName("BadOldClass2", false, classLoader);
107         assertShared(cls_BadOldClass2);
108         try {
109             cls_BadOldClass2.newInstance();
110             throw new RuntimeException("BadOldClass2 cannot be verified");
111         } catch (VerifyError expected) {}
112 
113         Class cls_BadNewClass = Class.forName("BadNewClass", false, classLoader);
114         assertShared(cls_BadNewClass);
115         try {
116             cls_BadNewClass.newInstance();
117             throw new RuntimeException("BadNewClass cannot be verified");
118         } catch (VerifyError expected) {}
119 
120         Class cls_BadNewClass2 = Class.forName("BadNewClass2", false, classLoader);
121         assertShared(cls_BadNewClass2);
122         try {
123             cls_BadNewClass2.newInstance();
124             throw new RuntimeException("BadNewClass2 cannot be verified");
125         } catch (VerifyError expected) {}
126 
127 
128         // Although Vehicle and Car are not specified in the classlist, they are archived as
129         // they were used during dumptime verification of GoodOldClass
130         assertShared(GoodOldClass.class);
131         assertShared(Vehicle.class);
132         assertShared(Car.class);
133 
134         GoodOldClass.doit(); // Should not fail
135     }
136 
137     static void assertShared(Class c) {
138         if (!wb.isSharedClass(c)) {
139             throw new RuntimeException("wb.isSharedClass(" + c.getName() + ") should be true");
140         }
141     }
142 
143     static void assertNotShared(Class c) {
144         if (wb.isSharedClass(c)) {
145             throw new RuntimeException("wb.isSharedClass(" + c.getName() + ") should be false");
146         }
147     }
148 }
149 
150 
151 class Unlinked {
152     static String doit() {
153         UnlinkedSuper sup = new UnlinkedSub();
154         return sup.doit();
155     }
156 }
157 
158 abstract class UnlinkedSuper {
159     abstract String doit();
160 }
161 
162 class UnlinkedSub extends UnlinkedSuper {
163     String doit() {
164         return "heyhey";
165     }
166 }
167 
168 class Foo {}
169 class NotFoo {}
170 
171 class Vehicle {}
172 class Car extends Vehicle {}