1 /*
   2  * Copyright (c) 2019, 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 A few edge cases where there's no class to be included in the dynamic archive.
  28  * @requires vm.cds
  29  * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/dynamicArchive/test-classes
  30  * @build StrConcatApp
  31  * @run driver ClassFileInstaller -jar strConcatApp.jar StrConcatApp
  32  * @run driver NoClassToArchive
  33  */
  34 
  35 import java.io.File;
  36 import jdk.test.lib.process.OutputAnalyzer;
  37 import jdk.test.lib.process.ProcessTools;
  38 
  39 public class NoClassToArchive extends DynamicArchiveTestBase {
  40     static final String warningMessage =
  41         "There is no class to be included in the dynamic archive";
  42     static final String classList = System.getProperty("test.classes") +
  43         File.separator + "NoClassToArchive.list";
  44     static final String appClass = "StrConcatApp";
  45 
  46     public static void main(String[] args) throws Exception {
  47         runTest(NoClassToArchive::testDefaultBase);
  48         runTest(NoClassToArchive::testCustomBase);
  49     }
  50 
  51     // (1) Test with default base archive + top archive
  52     static void testDefaultBase() throws Exception {
  53         String topArchiveName = getNewArchiveName("top");
  54         doTest(null, topArchiveName);
  55     }
  56 
  57     // (2) Test with custom base archive + top archive
  58     static void testCustomBase() throws Exception {
  59         String topArchiveName = getNewArchiveName("top2");
  60         String baseArchiveName = getNewArchiveName("base");
  61         doTestCustomBase(baseArchiveName, topArchiveName);
  62     }
  63 
  64     private static void doTest(String baseArchiveName, String topArchiveName) throws Exception {
  65         dump2(baseArchiveName, topArchiveName,
  66              "-Xlog:cds",
  67              "-Xlog:cds+dynamic=debug",
  68              "-Xlog:class+load=trace",
  69              "-version")
  70             .assertNormalExit(output -> {
  71                     if (output.getStdout().contains("jrt:/")) {
  72                         System.out.println("test skipped: this platform uses non-archived classes when running -version");
  73                     } else {
  74                         output.shouldContain(warningMessage);
  75                     }
  76                 });
  77 
  78         dump2(baseArchiveName, topArchiveName,
  79              "-Xlog:cds",
  80              "-Xlog:cds+dynamic=debug",
  81              "-Xlog:class+load=trace",
  82              "-help")
  83             .assertNormalExit(output -> {
  84                     // some classes will be loaded from the java.base module
  85                     output.shouldContain("java.text.MessageFormat source: jrt:/java.base");
  86                 });
  87     }
  88 
  89     private static void doTestCustomBase(String baseArchiveName, String topArchiveName) throws Exception {
  90         String appJar = ClassFileInstaller.getJarPath("strConcatApp.jar");
  91         // dump class list by running the StrConcatApp
  92         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
  93             true,
  94             "-XX:DumpLoadedClassList=" + classList,
  95             "-cp",
  96             appJar,
  97             appClass);
  98         OutputAnalyzer output = TestCommon.executeAndLog(pb, "dumpClassList");
  99         TestCommon.checkExecReturn(output, 0, true, "length = 0");
 100 
 101         // create a custom base archive based on the class list
 102         dumpBaseArchive(baseArchiveName, "-XX:SharedClassListFile=" + classList);
 103 
 104         // create a dynamic archive with the custom base archive
 105         // no class should be included in the dynamic archive
 106         dump2(baseArchiveName, topArchiveName, "-version")
 107             .assertNormalExit(out -> {
 108                     out.shouldMatch(warningMessage);
 109                 });
 110     }
 111 }