1 /*
   2  * Copyright (c) 2016, 2017, 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  * @test
  26  * @requires vm.cds
  27  * @summary classes which are not useable during run time should not be included in the classlist
  28  * @library /test/lib
  29  * @modules java.base/jdk.internal.misc
  30  *          jdk.jartool/sun.tools.jar
  31  * @build PatchModuleMain
  32  * @run main PatchModuleClassList
  33  */
  34 
  35 import java.nio.file.Files;
  36 import java.nio.file.Paths;
  37 import jdk.test.lib.compiler.InMemoryJavaCompiler;
  38 import jdk.test.lib.process.OutputAnalyzer;
  39 import jdk.test.lib.process.ProcessTools;
  40 
  41 public class PatchModuleClassList {
  42     private static final String BOOT_CLASS = "javax/naming/spi/NamingManager";
  43     private static final String PLATFORM_CLASS = "javax/transaction/InvalidTransactionException";
  44 
  45     public static void main(String args[]) throws Throwable {
  46         // Case 1. A class to be loaded by the boot class loader
  47 
  48         // Create a class file in the module java.naming. This class file
  49         // will be put in the javanaming.jar file.
  50         String source = "package javax.naming.spi; "                +
  51                         "public class NamingManager { "             +
  52                         "    static { "                             +
  53                         "        System.out.println(\"I pass!\"); " +
  54                         "    } "                                    +
  55                         "}";
  56 
  57         ClassFileInstaller.writeClassToDisk(BOOT_CLASS,
  58              InMemoryJavaCompiler.compile(BOOT_CLASS.replace('/', '.'), source, "--patch-module=java.naming"),
  59              System.getProperty("test.classes"));
  60 
  61         // Build the jar file that will be used for the module "java.naming".
  62         BasicJarBuilder.build("javanaming", BOOT_CLASS);
  63         String moduleJar = BasicJarBuilder.getTestJar("javanaming.jar");
  64 
  65         String classList = "javanaming.list";
  66         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
  67             true,
  68             "-XX:DumpLoadedClassList=" + classList,
  69             "--patch-module=java.naming=" + moduleJar,
  70             "PatchModuleMain", BOOT_CLASS.replace('/', '.'));
  71         new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
  72 
  73         // check the generated classlist file
  74         String content = new String(Files.readAllBytes(Paths.get(classList)));
  75         if (content.indexOf(BOOT_CLASS) >= 0) {
  76             throw new RuntimeException(BOOT_CLASS + " should not be in the classlist");
  77         }
  78 
  79         // Case 2. A class to be loaded by the platform class loader
  80 
  81         // Create a class file in the module java.transaction. This class file
  82         // will be put in the javatransaction.jar file.
  83         source = "package javax.transaction; "                 +
  84                  "public class InvalidTransactionException { " +
  85                  "    static { "                               +
  86                  "        System.out.println(\"I pass!\"); "   +
  87                  "    } "                                      +
  88                  "}";
  89 
  90         ClassFileInstaller.writeClassToDisk(PLATFORM_CLASS,
  91              InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "--patch-module=java.transaction"),
  92              System.getProperty("test.classes"));
  93 
  94         // Build the jar file that will be used for the module "java.transaction".
  95         BasicJarBuilder.build("javatransaction", PLATFORM_CLASS);
  96         moduleJar = BasicJarBuilder.getTestJar("javatransaction.jar");
  97 
  98         classList = "javatransaction.list";
  99         pb = ProcessTools.createJavaProcessBuilder(
 100             true,
 101             "-XX:DumpLoadedClassList=" + classList,
 102             "--patch-module=java.naming=" + moduleJar,
 103             "PatchModuleMain", PLATFORM_CLASS.replace('/', '.'));
 104         new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
 105 
 106         // check the generated classlist file
 107         content = new String(Files.readAllBytes(Paths.get(classList)));
 108         if (content.indexOf(PLATFORM_CLASS) >= 0) {
 109             throw new RuntimeException(PLATFORM_CLASS + " should not be in the classlist");
 110         }
 111 
 112         // Case 3. A class to be loaded from the bootclasspath/a
 113 
 114         // Create a simple class file
 115         source = "public class Hello { "                         +
 116                  "    public static void main(String args[]) { " +
 117                  "        System.out.println(\"Hello\"); "       +
 118                  "    } "                                        +
 119                  "}";
 120 
 121         ClassFileInstaller.writeClassToDisk("Hello",
 122              InMemoryJavaCompiler.compile("Hello", source),
 123              System.getProperty("test.classes"));
 124 
 125         // Build hello.jar
 126         BasicJarBuilder.build("hello", "Hello");
 127         moduleJar = BasicJarBuilder.getTestJar("hello.jar");
 128 
 129         classList = "hello.list";
 130         pb = ProcessTools.createJavaProcessBuilder(
 131             true,
 132             "-XX:DumpLoadedClassList=" + classList,
 133             "-Xbootclasspath/a:" + moduleJar,
 134             "Hello");
 135         new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
 136 
 137         // check the generated classlist file
 138         content = new String(Files.readAllBytes(Paths.get(classList)));
 139         if (content.indexOf("Hello") < 0) {
 140             throw new RuntimeException("Hello should be in the classlist");
 141         }
 142     }
 143 }