1 /* 2 * Copyright (c) 2016, 2018, 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 // Structure of the test: 26 // TransformRelatedClassesAppCDS -- common main test driver 27 // Invoked from test driver classes: 28 // TransformInterfaceAndImplementor, TransformSuperAndSubClasses.java 29 // prepares test artifacts, launches tests, checks results 30 // SuperClazz, SubClass -- classes under test 31 // Interface, Implementor -- classes under test 32 // TransformerAgent -- an agent that is used when JVM-under-test is executed 33 // to transform specific strings inside specified classes 34 // TransformerAgent.mf - accompanies transformer agent 35 // CustomLoaderApp -- a test "application" that is used to load 36 // classes-under-test (Parent, Child) via custom class loader, using 37 // AppCDS-v2 mechanism (unregistered custom loaders, aka FP) 38 // This "app" is launched in a child process by this driver with sharing on. 39 40 import java.io.File; 41 import java.util.ArrayList; 42 import jdk.test.lib.Platform; 43 import jdk.test.lib.process.OutputAnalyzer; 44 45 // This class is intended to test 2 parent-child relationships: 46 // 1. Base Class (parent) and Derived Class (child) 47 // 2. Interface (parent) and Implementor (child) 48 // Parameters to main(): parent, child 49 50 public class TransformRelatedClassesAppCDS extends TransformRelatedClasses { 51 private static void log(String msg, Object... args) { 52 String msg0 = String.format(msg, args); 53 System.out.println("TransformRelatedClassesAppCDS: " + msg0); 54 } 55 56 // Initial Test Matrix: 57 // (ParentTransformed = true/false, ChildTransformed = true/false) x 58 // (BootCDS - see open tests, AppCDS-v1, AppCDS-v2-unregistered) 59 // Total cases: 2 x 4 = 8 60 public static void main(String args[]) throws Exception { 61 TransformRelatedClassesAppCDS test = 62 new TransformRelatedClassesAppCDS(args[0], args[1]); 63 64 test.prepareAgent(agentClasses); 65 66 // Test Table 67 // testCaseId | transformParent | tranformChild | isParentExpectedShared | isChildExpectedShared 68 ArrayList<TestEntry> testTable = new ArrayList<>(); 69 70 // base case - no tranformation - all expected to be shared 71 testTable.add(new TestEntry(0, false, false, true, true)); 72 73 // transform parent only - both parent and child should not be shared 74 testTable.add(new TestEntry(1, true, false, false, false)); 75 76 // transform parent and child - both parent and child should not be shared 77 testTable.add(new TestEntry(2, true, true, false, false)); 78 79 // transform child only - parent should still be shared, but not child 80 testTable.add(new TestEntry(3, false, true, true, false)); 81 82 // run the tests 83 test.runWithAppLoader(testTable); 84 test.runWithCustomLoader(testTable); 85 } 86 87 88 public TransformRelatedClassesAppCDS(String parent, String child) { 89 super(parent, child); 90 91 // a trick to get it compiled by jtreg 92 CustomLoaderApp.ping(); 93 } 94 95 96 private void prepareAgent(String[] agentClasses) throws Exception { 97 String manifest = "../../../../testlibrary/jvmti/TransformerAgent.mf"; 98 agentJar = ClassFileInstaller.writeJar("TransformerAgent.jar", 99 ClassFileInstaller.Manifest.fromSourceFile(manifest), 100 agentClasses); 101 } 102 103 104 private void runWithAppLoader(ArrayList<TestEntry> testTable) throws Exception { 105 String appJar = writeJar("app", testClasses); 106 107 // create an archive 108 OutputAnalyzer out = TestCommon.dump(appJar, testClasses); 109 TestCommon.checkDump(out); 110 111 // execute with archive 112 for (TestEntry entry : testTable) { 113 log("runTestWithAppLoader(): testCaseId = %d", entry.testCaseId); 114 String params = TransformTestCommon.getAgentParams(entry, parent, child); 115 String agentParam = String.format("-javaagent:%s=%s", agentJar, params); 116 117 TestCommon.run("-Xlog:class+load=info", "-cp", appJar, 118 agentParam, child) 119 .assertNormalExit(output -> TransformTestCommon.checkResults(entry, output, parent, child)); 120 } 121 } 122 123 124 private String[] getCustomClassList(String loaderType, String customJar) { 125 String type = child + "-" + loaderType; 126 127 switch (type) { 128 129 case "SubClass-unregistered": 130 return new String[] { 131 "CustomLoaderApp", 132 "java/lang/Object id: 0", 133 parent + " id: 1 super: 0 source: " + customJar, 134 child + " id: 2 super: 1 source: " + customJar, 135 }; 136 137 case "Implementor-unregistered": 138 return new String[] { 139 "CustomLoaderApp", 140 "java/lang/Object id: 0", 141 parent + " id: 1 super: 0 source: " + customJar, 142 child + " id: 2 super: 0 interfaces: 1 source: " + customJar, 143 }; 144 145 default: 146 throw new IllegalArgumentException("getCustomClassList - wrong type: " + type); 147 } 148 } 149 150 151 private void runWithCustomLoader(ArrayList<TestEntry> testTable) throws Exception { 152 if (!Platform.areCustomLoadersSupportedForCDS()) { 153 log("custom loader not supported for this platform" + 154 " - skipping test case for custom loader"); 155 return; 156 } 157 158 String appClasses[] = { 159 "CustomLoaderApp", 160 }; 161 162 String customClasses[] = { parent, child }; 163 164 // create jar files: appJar, customJar (for custom loaders to load classes from) 165 String appJar = writeJar("custldr-app", appClasses); 166 String customJar = writeJar("custldr-custom", customClasses); 167 168 for (TestEntry entry : testTable) { 169 log("runTestWithCustomLoader(): testCaseId = %d", entry.testCaseId); 170 // unregistered (aka FP) case 171 String[] classList = getCustomClassList("unregistered",customJar); 172 execAndCheckWithCustomLoader(entry, "unregistered", classList, 173 appJar, agentJar, customJar); 174 } 175 } 176 177 178 private void 179 execAndCheckWithCustomLoader(TestEntry entry, String loaderType, 180 String[] classList, String appJar, 181 String agentJar, String customJar) 182 throws Exception { 183 184 OutputAnalyzer out = TestCommon.dump(appJar, classList); 185 TestCommon.checkDump(out); 186 187 String agentParam = "-javaagent:" + agentJar + "=" + 188 TransformTestCommon.getAgentParams(entry, parent, child); 189 190 TestCommon.run("-Xlog:class+load=info", 191 "-cp", appJar, 192 "--add-opens=java.base/java.security=ALL-UNNAMED", 193 agentParam, 194 "CustomLoaderApp", 195 customJar, loaderType, child) 196 .assertNormalExit(output -> TransformTestCommon.checkResults(entry, output, parent, child)); 197 } 198 199 200 private String writeJar(String type, String[] classes) 201 throws Exception { 202 String jarName = String.format("%s-%s.jar", child, type); 203 return ClassFileInstaller.writeJar(jarName, classes); 204 } 205 }