1 /* 2 * Copyright (c) 2016, 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 // 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 TestCommon.run("-Xlog:class+load=info", "-cp", appJar, 117 agentParam, child) 118 .assertNormalExit(output -> TransformTestCommon.checkResults(entry, output, parent, child)); 119 } 120 } 121 122 123 private String[] getCustomClassList(String loaderType, String customJar) { 124 String type = child + "-" + loaderType; 125 126 switch (type) { 127 128 case "SubClass-unregistered": 129 return new String[] { 130 "CustomLoaderApp", 131 "java/lang/Object id: 0", 132 parent + " id: 1 super: 0 source: " + customJar, 133 child + " id: 2 super: 1 source: " + customJar, 134 }; 135 136 case "Implementor-unregistered": 137 return new String[] { 138 "CustomLoaderApp", 139 "java/lang/Object id: 0", 140 parent + " id: 1 super: 0 source: " + customJar, 141 child + " id: 2 super: 0 interfaces: 1 source: " + customJar, 142 }; 143 144 default: 145 throw new IllegalArgumentException("getCustomClassList - wrong type: " + type); 146 } 147 } 148 149 150 private void runWithCustomLoader(ArrayList<TestEntry> testTable) throws Exception { 151 if (!Platform.areCustomLoadersSupportedForCDS()) { 152 log("custom loader not supported for this platform" + 153 " - skipping test case for custom loader"); 154 return; 155 } 156 157 if (TestCommon.isDynamicArchive()) { 158 log("custom loader class list not applicable to dynamic archive" + 159 " - skipping test case for custom loader"); 160 return; 161 } 162 163 String appClasses[] = { 164 "CustomLoaderApp", 165 }; 166 167 String customClasses[] = { parent, child }; 168 169 // create jar files: appJar, customJar (for custom loaders to load classes from) 170 String appJar = writeJar("custldr-app", appClasses); 171 String customJar = writeJar("custldr-custom", customClasses); 172 173 for (TestEntry entry : testTable) { 174 log("runTestWithCustomLoader(): testCaseId = %d", entry.testCaseId); 175 // unregistered (aka FP) case 176 String[] classList = getCustomClassList("unregistered",customJar); 177 execAndCheckWithCustomLoader(entry, "unregistered", classList, 178 appJar, agentJar, customJar); 179 } 180 } 181 182 183 private void 184 execAndCheckWithCustomLoader(TestEntry entry, String loaderType, 185 String[] classList, String appJar, 186 String agentJar, String customJar) 187 throws Exception { 188 189 OutputAnalyzer out = TestCommon.dump(appJar, classList); 190 TestCommon.checkDump(out); 191 192 String agentParam = "-javaagent:" + agentJar + "=" + 193 TransformTestCommon.getAgentParams(entry, parent, child); 194 195 TestCommon.run("-Xlog:class+load=info", 196 "-cp", appJar, 197 agentParam, 198 "CustomLoaderApp", 199 customJar, loaderType, child) 200 .assertNormalExit(output -> TransformTestCommon.checkResults(entry, output, parent, child)); 201 } 202 203 204 private String writeJar(String type, String[] classes) 205 throws Exception { 206 String jarName = String.format("%s-%s.jar", child, type); 207 return ClassFileInstaller.writeJar(jarName, classes); 208 } 209 }