--- old/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/ReplaceCriticalClasses.java 2018-10-21 22:33:27.430976937 -0700 +++ new/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/ReplaceCriticalClasses.java 2018-10-21 22:33:27.146966101 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,34 +27,168 @@ * @summary Tests how CDS works when critical library classes are replaced with JVMTI ClassFileLoadHook * @library /test/lib * @requires vm.cds - * - * @comment CDS should not be disabled -- these critical classes will be replaced because JvmtiExport::early_class_hook_env() is true. - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=+early,java/lang/Object,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=+early,java/lang/String,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=+early,java/lang/Cloneable,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=+early,java/io/Serializable,XXX,XXX -showversion ReplaceCriticalClasses - * - * @comment CDS should not be disabled -- these critical classes cannot be replaced because JvmtiExport::early_class_hook_env() is false. - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/lang/Object,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/lang/String,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/lang/Cloneable,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/io/Serializable,XXX,XXX -showversion ReplaceCriticalClasses - * - * @comment Try to replace classes that are used by the archived subgraph graphs. As of 2018/10/21 the classes won't be replaced because - * all archived subgraphs were loaded in JVMTI_PHASE_PRIMORDIAL. - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/util/ArrayList,XXX,XXX -verbose -showversion -Xlog:cds+heap=debug ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/lang/module/ResolvedModule,XXX,XXX -verbose -showversion -Xlog:cds+heap=debug ReplaceCriticalClasses - * - * @comment Replace classes that are loaded after JVMTI_PHASE_PRIMORDIAL. It's OK to replace such classes even when CDS is enabled. - * Nothing bad should happen. - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=jdk/internal/vm/PostVMInitHook,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/util/Locale,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=sun/util/locale/BaseLocale,XXX,XXX -showversion ReplaceCriticalClasses - * @run main/othervm/native -Xshare:auto -agentlib:SimpleClassFileLoadHook=java/lang/Readable,XXX,XXX -showversion ReplaceCriticalClasses + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox + * @run main/othervm/native ReplaceCriticalClasses */ +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + public class ReplaceCriticalClasses { - public static void main(String args[]) { + public static void main(String args[]) throws Throwable { + if (args.length == 0) { + launchChildProcesses(); + } else if (args.length == 3 && args[0].equals("child")) { + Class klass = Class.forName(args[2].replace("/", ".")); + if (args[1].equals("-shared")) { + testInChild(true, klass); + } else if (args[1].equals("-notshared")) { + testInChild(false, klass); + } else { + throw new RuntimeException("Unknown child exec option " + args[1]); + } + return; + } else { + throw new RuntimeException("Usage: @run main/othervm/native ReplaceCriticalClasses"); + } + } + + static void launchChildProcesses() throws Throwable { + String tests[] = { + // CDS should be disabled -- these critical classes will be replaced + // because JvmtiExport::early_class_hook_env() is true. + "-early -notshared java/lang/Object", + "-early -notshared java/lang/String", + "-early -notshared java/lang/Cloneable", + "-early -notshared java/io/Serializable", + + // CDS should not be disabled -- these critical classes cannot be replaced because JvmtiExport::early_class_hook_env() is false. + "java/lang/Object", + "java/lang/String", + "java/lang/Cloneable", + "java/io/Serializable", + + // Try to replace classes that are used by the archived subgraph graphs. + "-subgraph java/util/ArrayList", + "-subgraph java/lang/module/ResolvedModule", + + // Replace classes that are loaded after JVMTI_PHASE_PRIMORDIAL. It's OK to replace such + // classes even when CDS is enabled. Nothing bad should happen. + "-notshared jdk/internal/vm/PostVMInitHook", + "-notshared java/util/Locale", + "-notshared sun/util/locale/BaseLocale", + "-notshared java/lang/Readable", + }; + + int n = 0; + for (String s : tests) { + System.out.println("Test case[" + (n++) + "] = \"" + s + "\""); + String args[] = s.split("\\s+"); // split by space character + launchChild(args); + } + } + + static void launchChild(String args[]) throws Throwable { + if (args.length < 1) { + throw new RuntimeException("Invalid test case. Should be <-early> <-subgraph> <-notshared> klassName"); + } + String klassName = null; + String early = ""; + boolean subgraph = false; + String shared = "-shared"; + + for (int i=0; i { + if (expectDisable) { + out.shouldContain("UseSharedSpaces: CDS is disabled because early JVMTI ClassFileLoadHook is in use."); + System.out.println("CDS disabled as expected"); + } + if (checkSubgraph && false) { + // As of 2018/10/21 the classes in the archived subgraphs won't be + // replaced because all archived subgraphs were loaded in JVMTI_PHASE_PRIMORDIAL. + // + // This is the first class to be loaded after JVMTI has exited JVMTI_PHASE_PRIMORDIAL. + // Make sure no subgraphs are loaded afterwards. + // + // Can't use out.shouldNotMatch() because that doesn't match across multiple lines. + String firstNonPrimordialClass = "jdk.jfr.internal.EventWriter"; + String regexp = firstNonPrimordialClass + ".*initialize_from_archived_subgraph"; + Pattern regex = Pattern.compile(regexp, Pattern.DOTALL); + Matcher matcher = regex.matcher(out.getStdout()); + if (matcher.find()) { + out.reportDiagnosticSummary(); + throw new RuntimeException("'" + regexp + + "' found in stdout: '" + matcher.group() + "' \n"); + } + } + }); + } + + static void testInChild(boolean shouldBeShared, Class klass) { + WhiteBox wb = WhiteBox.getWhiteBox(); + + if (shouldBeShared && !wb.isSharedClass(klass)) { + throw new RuntimeException(klass + " should be shared but but actually is not."); + } + if (!shouldBeShared && wb.isSharedClass(klass)) { + throw new RuntimeException(klass + " should not be shared but actually is."); + } + System.out.println("wb.isSharedClass(klass): " + wb.isSharedClass(klass) + " == " + shouldBeShared); + String strings[] = { // interned strings from j.l.Object "@", @@ -84,4 +218,4 @@ // the above operations should succeed. System.out.println("If I can come to here without crashing, things should be OK"); } -} \ No newline at end of file +}