1 /*
  2  * Copyright (c) 2021, 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  * @summary -XX:DumpLoadedClassList should support custom loaders
 28  * @bug 8265602
 29  * @requires vm.cds
 30  * @requires vm.cds.custom.loaders
 31  * @library /test/lib
 32  *          /test/hotspot/jtreg/runtime/cds/appcds
 33  *          /test/hotspot/jtreg/runtime/cds/appcds/test-classes
 34  *          test-classes
 35  * @build CustomLoaderApp OldClass CustomLoadee CustomLoadee2
 36  *        CustomLoadee3Child CustomLoadee4WithLambda
 37  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar CustomLoaderApp
 38  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar custom.jar
 39  *             OldClass CustomLoadee
 40  *             CustomLoadee2 CustomInterface2_ia CustomInterface2_ib
 41  *             CustomLoadee3 CustomLoadee3Child
 42  *             CustomLoadee4WithLambda
 43  * @run driver CustomClassListDump
 44  */
 45 
 46 import java.nio.file.Files;
 47 import java.nio.file.Paths;
 48 import java.util.regex.Matcher;
 49 import java.util.regex.Pattern;
 50 import jdk.test.lib.cds.CDSOptions;
 51 import jdk.test.lib.cds.CDSTestUtils;
 52 import jdk.test.lib.helpers.ClassFileInstaller;
 53 
 54 public class CustomClassListDump {
 55     private static String appJar = ClassFileInstaller.getJarPath("app.jar");
 56     private static String customJar = ClassFileInstaller.getJarPath("custom.jar");
 57     private static String classList = "app.list";
 58     private static String commandLine[] = {
 59         "-cp", appJar,
 60         "CustomLoaderApp",
 61         customJar,
 62         "unregistered",
 63         "CustomLoadee",
 64         "CustomLoadee2",
 65         "CustomLoadee3Child",
 66         "CustomLoadee4WithLambda",
 67         "OldClass",
 68     };
 69 
 70     public static void main(String[] args) throws Exception {
 71         // Dump the classlist and check that custom-loader classes are in there.
 72         CDSTestUtils.dumpClassList(classList, commandLine)
 73             .assertNormalExit();
 74 
 75         String listData = new String(Files.readAllBytes(Paths.get(classList)));
 76         check(listData, true, "CustomLoaderApp id: [0-9]+");
 77         check(listData, true, "CustomLoadee id: [0-9]+ super: [0-9]+ interfaces: [0-9]+ source: .*/custom.jar");
 78         check(listData, true, "CustomInterface2_ia id: [0-9]+ super: [0-9]+ source: .*/custom.jar");
 79         check(listData, true, "CustomInterface2_ib id: [0-9]+ super: [0-9]+ source: .*/custom.jar");
 80         check(listData, true, "CustomLoadee2 id: [0-9]+ super: [0-9]+ interfaces: [0-9]+ [0-9]+ [0-9]+ source: .*/custom.jar");
 81         check(listData, true, "CustomLoadee3 id: [0-9]+ super: [0-9]+ interfaces: [0-9]+ source: .*/custom.jar");
 82         check(listData, true, "CustomLoadee3Child id: [0-9]+ super: [0-9]+ source: .*/custom.jar");
 83         check(listData, true, "CustomLoadee4WithLambda id: [0-9]+ super: [0-9]+ interfaces: [0-9]+ source: .*/custom.jar");
 84 
 85         // We don't support archiving of Lambda proxies for custom loaders.
 86         check(listData, false, "@lambda-proxy.*CustomLoadee4WithLambda");
 87 
 88         // Dump the static archive
 89         CDSOptions opts = (new CDSOptions())
 90             .addPrefix("-cp", appJar,
 91                        "-Xlog:cds+class=debug",
 92                        "-XX:SharedClassListFile=" + classList);
 93         CDSTestUtils.createArchiveAndCheck(opts)
 94             .shouldContain("unreg CustomLoadee")
 95             .shouldContain("unreg CustomLoadee2")
 96             .shouldContain("unreg CustomLoadee3Child")
 97             .shouldContain("unreg OldClass ** unlinked");
 98 
 99         // Use the dumped static archive
100         opts = (new CDSOptions())
101             .setUseVersion(false)
102             .addPrefix("-cp", appJar)
103             .addSuffix("-Xlog:class+load,verification")
104             .addSuffix(commandLine);
105         CDSTestUtils.run(opts)
106             .assertNormalExit("CustomLoadee source: shared objects file",
107                               "CustomLoadee2 source: shared objects file",
108                               "CustomLoadee3Child source: shared objects file",
109                               "OldClass source: shared objects file",
110                               "Verifying class OldClass with old format");
111     }
112 
113     static void check(String listData, boolean mustMatch, String regexp) throws Exception {
114         Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE);
115         Matcher matcher = pattern.matcher(listData);
116         boolean found = matcher.find();
117         if (mustMatch && !found) {
118             System.out.println(listData);
119             throw new RuntimeException("Pattern \"" + regexp + "\" not found in classlist");
120         }
121 
122         if (!mustMatch && found) {
123             throw new RuntimeException("Pattern \"" + regexp + "\" found in in classlist: \""
124                                        + matcher.group() + "\"");
125         }
126     }
127 }