< prev index next >

test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/ReplaceCriticalClasses.java

Print this page

*** 1,7 **** /* ! * Copyright (c) 2016, 2017, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 25,62 **** /* * @test * @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 */ public class ReplaceCriticalClasses { ! public static void main(String args[]) { String strings[] = { // interned strings from j.l.Object "@", "nanosecond timeout value out of range", "timeoutMillis value is negative", --- 25,196 ---- /* * @test * @summary Tests how CDS works when critical library classes are replaced with JVMTI ClassFileLoadHook * @library /test/lib * @requires vm.cds ! * @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[]) 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<args.length-1; i++) { ! String opt = args[i]; ! if (opt.equals("-early")) { ! early = "-early,"; ! } else if (opt.equals("-subgraph")) { ! subgraph = true; ! } else if (opt.equals("-notshared")) { ! shared = opt; ! } else { ! throw new RuntimeException("Unknown option: " + opt); ! } ! } ! klassName = args[args.length-1]; ! Class.forName(klassName.replace("/", ".")); // make sure it's a valid class ! ! // We will pass an option like "-agentlib:SimpleClassFileLoadHook=java/util/Locale,XXX,XXX". ! // The SimpleClassFileLoadHook agent would attempt to hook the java/util/Locale class ! // but leave the class file bytes unchanged (it replaces all bytes "XXX" with "XXX", i.e., ! // a no-op). JVMTI doesn't check the class file bytes returned by the agent, so as long ! // as the agent returns a buffer, it will not load the class from CDS, and will instead ! // load the class by parsing the buffer. ! // ! // Note that for safety we don't change the contents of the class file bytes. If in the ! // future JVMTI starts checking the contents of the class file bytes, this test would need ! // to be updated. (You'd see the test case with java/util/Locale staring to fail). ! String agent = "-agentlib:SimpleClassFileLoadHook=" + early + klassName + ",XXX,XXX"; ! ! CDSOptions opts = new CDSOptions(); ! opts.setXShareMode("auto") ! .addSuffix("-showversion") ! .addSuffix("-Xlog:cds") ! .addSuffix("-XX:+UnlockDiagnosticVMOptions") ! .addSuffix(agent) ! .addSuffix("-XX:+WhiteBoxAPI") ! .addSuffix("-Xbootclasspath/a:" + ClassFileInstaller.getJarPath("whitebox.jar")); ! ! if (subgraph) { ! opts.addSuffix("-Xlog:cds+heap"); ! opts.addSuffix("-Xlog:class+load"); ! } ! ! opts.addSuffix("ReplaceCriticalClasses") ! .addSuffix("child") ! .addSuffix(shared) ! .addSuffix(klassName) ! .setUseSystemArchive(true) ! .setUseVersion(false); ! ! final boolean expectDisable = !early.equals(""); ! final boolean checkSubgraph = subgraph; ! CDSTestUtils.run(opts).assertNormalExit(out -> { ! 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 "@", "nanosecond timeout value out of range", "timeoutMillis value is negative",
< prev index next >