8201375: Add the AllowArchivingWithJavaAgent diagnostic vm option to allow the use of the -javaagent option during CDS dumping

Allow Java agent during CDS dumping if the AllowArchivingWithJavaAgent dignostic option is specified.

Reviewed-by: iklam, jiangli, sspitsyn, dcubed
This commit is contained in:
Calvin Cheung 2018-11-16 16:10:25 -08:00
parent 7a30c97753
commit 8761824649
13 changed files with 321 additions and 4 deletions

View File

@ -210,6 +210,7 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
_verify_remote = BytecodeVerificationRemote;
_has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
_shared_base_address = SharedBaseAddress;
_allow_archiving_with_java_agent = AllowArchivingWithJavaAgent;
}
void SharedClassPathEntry::init(const char* name, bool is_modules_image, TRAPS) {
@ -1358,6 +1359,21 @@ bool FileMapHeader::validate() {
return false;
}
// Java agents are allowed during run time. Therefore, the following condition is not
// checked: (!_allow_archiving_with_java_agent && AllowArchivingWithJavaAgent)
// Note: _allow_archiving_with_java_agent is set in the shared archive during dump time
// while AllowArchivingWithJavaAgent is set during the current run.
if (_allow_archiving_with_java_agent && !AllowArchivingWithJavaAgent) {
FileMapInfo::fail_continue("The setting of the AllowArchivingWithJavaAgent is different "
"from the setting in the shared archive.");
return false;
}
if (_allow_archiving_with_java_agent) {
warning("This archive was created with AllowArchivingWithJavaAgent. It should be used "
"for testing purposes only and should not be used in a production environment");
}
return true;
}

View File

@ -151,6 +151,7 @@ struct FileMapHeader : public CDSFileMapHeaderBase {
bool _verify_remote; // BytecodeVerificationRemote setting
bool _has_platform_or_app_classes; // Archive contains app classes
size_t _shared_base_address; // SharedBaseAddress used at dump time
bool _allow_archiving_with_java_agent; // setting of the AllowArchivingWithJavaAgent option
void set_has_platform_or_app_classes(bool v) {
_has_platform_or_app_classes = v;

View File

@ -1494,6 +1494,12 @@ void VM_PopulateDumpSharedSpace::doit() {
if (PrintSystemDictionaryAtExit) {
SystemDictionary::print();
}
if (AllowArchivingWithJavaAgent) {
warning("This archive was created with AllowArchivingWithJavaAgent. It should be used "
"for testing purposes only and should not be used in a production environment");
}
// There may be other pending VM operations that operate on the InstanceKlasses,
// which will fail because InstanceKlasses::remove_unshareable_info()
// has been called. Forget these operations and exit the VM directly.

View File

@ -2431,6 +2431,9 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G);
"Average number of symbols per bucket in shared table") \
range(2, 246) \
\
diagnostic(bool, AllowArchivingWithJavaAgent, false, \
"Allow Java agent to be run with CDS dumping") \
\
diagnostic(bool, PrintMethodHandleStubs, false, \
"Print generated stub code for method handles") \
\

View File

@ -4088,6 +4088,17 @@ void Threads::create_vm_init_agents() {
JvmtiExport::enter_onload_phase();
for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) {
// CDS dumping does not support native JVMTI agent.
// CDS dumping supports Java agent if the AllowArchivingWithJavaAgent diagnostic option is specified.
if (DumpSharedSpaces) {
if(!agent->is_instrument_lib()) {
vm_exit_during_cds_dumping("CDS dumping does not support native JVMTI agent, name", agent->name());
} else if (!AllowArchivingWithJavaAgent) {
vm_exit_during_cds_dumping(
"Must enable AllowArchivingWithJavaAgent in order to run Java agent during CDS dumping");
}
}
OnLoadEntry_t on_load_entry = lookup_agent_on_load(agent);
if (on_load_entry != NULL) {
@ -4100,6 +4111,7 @@ void Threads::create_vm_init_agents() {
vm_exit_during_initialization("Could not find Agent_OnLoad function in the agent library", agent->name());
}
}
JvmtiExport::enter_primordial_phase();
}

View File

@ -47,6 +47,8 @@ public class AnonVmClassesDuringDump {
"AnonVmClassesDuringDumpTransformer",
};
public static String cdsDiagnosticOption = "-XX:+AllowArchivingWithJavaAgent";
public static void main(String[] args) throws Throwable {
String agentJar =
ClassFileInstaller.writeJar("AnonVmClassesDuringDumpTransformer.jar",
@ -58,6 +60,7 @@ public class AnonVmClassesDuringDump {
TestCommon.testDump(appJar, TestCommon.list("Hello"),
"-javaagent:" + agentJar,
"-XX:+UnlockDiagnosticVMOptions", cdsDiagnosticOption,
// Set the following property to see logs for dynamically generated classes
// in STDOUT
"-Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true");
@ -70,11 +73,13 @@ public class AnonVmClassesDuringDump {
String suffix = ".*source: shared objects file.*";
String pattern = prefix + class_pattern + suffix;
// during run time, anonymous classes shouldn't be loaded from the archive
TestCommon.run("-cp", appJar, "Hello")
TestCommon.run("-cp", appJar,
"-XX:+UnlockDiagnosticVMOptions", cdsDiagnosticOption, "Hello")
.assertNormalExit(output -> output.shouldNotMatch(pattern));
// inspect the archive and make sure no anonymous class is in there
TestCommon.run("-cp", appJar,
"-XX:+UnlockDiagnosticVMOptions", cdsDiagnosticOption,
"-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary", "Hello")
.assertNormalExit(output -> output.shouldNotMatch(class_pattern));
}

View File

@ -64,14 +64,17 @@ public class GCDuringDump {
// i = 1 -- run with agent = cause extra GCs
String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
String extraOption = (i == 0) ? "-showversion" : "-XX:+AllowArchivingWithJavaAgent";
TestCommon.testDump(appJar, TestCommon.list("Hello"),
"-XX:+UnlockDiagnosticVMOptions", extraOption,
extraArg, "-Xmx32m", gcLog);
TestCommon.run(
"-cp", appJar,
"-Xmx32m",
"-XX:+PrintSharedSpaces",
"-XX:+UnlockDiagnosticVMOptions", extraOption,
gcLog,
"Hello")
.assertNormalExit();

View File

@ -88,11 +88,12 @@ public class GCSharedStringsDuringDump {
// i = 1 -- run with agent = cause extra GCs
String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
String extraOption = (i == 0) ? "-showversion" : "-XX:+AllowArchivingWithJavaAgent";
OutputAnalyzer output = TestCommon.dump(
appJar, TestCommon.list("GCSharedStringsDuringDumpWb"),
bootClassPath, extraArg, "-Xmx32m", gcLog,
"-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile);
"-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile,
"-XX:+UnlockDiagnosticVMOptions", extraOption);
if (output.getStdout().contains("Too many string space regions") ||
output.getStderr().contains("Unable to write archive heap memory regions") ||
@ -104,15 +105,19 @@ public class GCSharedStringsDuringDump {
TestCommon.testDump(
appJar, TestCommon.list("GCSharedStringsDuringDumpWb"),
bootClassPath, extraArg, "-Xmx8g", "-XX:NewSize=8m", gcLog,
"-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile);
"-XX:SharedArchiveConfigFile=" + sharedArchiveCfgFile,
"-XX:+UnlockDiagnosticVMOptions", extraOption);
}
TestCommon.run(
"-cp", appJar,
bootClassPath,
extraArg,
"-Xlog:cds=info,class+path=info",
"-Xmx32m",
"-XX:+PrintSharedSpaces",
"-XX:+UnlockDiagnosticVMOptions",
extraOption,
"-XX:+WhiteBoxAPI",
"-XX:SharedReadOnlySize=30m",
gcLog,

View File

@ -0,0 +1,119 @@
/*
* 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary CDS dumping with java agent.
* @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes
* @requires vm.cds
* @requires vm.flavor != "minimal"
* @modules jdk.jartool/sun.tools.jar
* @build SimpleAgent Hello
* @run main/othervm DumpingWithJavaAgent
*/
import jdk.test.lib.cds.CDSOptions;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class DumpingWithJavaAgent {
public static String appClasses[] = {
"Hello",
};
public static String agentClasses[] = {
"SimpleAgent",
};
public static String warningMessages[] = {
"This archive was created with AllowArchivingWithJavaAgent",
"It should be used for testing purposes only and should not be used in a production environment",
};
public static String errorMessage =
"The setting of the AllowArchivingWithJavaAgent is different from the setting in the shared archive.";
public static String diagnosticOption = "-XX:+AllowArchivingWithJavaAgent";
public static void main(String[] args) throws Throwable {
String agentJar =
ClassFileInstaller.writeJar("SimpleAgent.jar",
ClassFileInstaller.Manifest.fromSourceFile("SimpleAgent.mf"),
agentClasses);
String appJar =
ClassFileInstaller.writeJar("DumpingWithJavaAgent.jar", appClasses);
// CDS dumping with a java agent with the AllowArchvingWithJavaAgent diagnostic option.
OutputAnalyzer output = TestCommon.testDump(appJar, TestCommon.list("Hello"),
"-XX:+UnlockDiagnosticVMOptions", diagnosticOption,
"-javaagent:" + agentJar);
TestCommon.checkDump(output);
output.shouldContain(warningMessages[0]);
output.shouldContain(warningMessages[1]);
output.shouldContain("inside SimpleAgent");
// Using the archive with the AllowArchvingWithJavaAgent diagnostic option.
output = TestCommon.exec(
appJar,
"-Xlog:class+load=trace",
"-XX:+UnlockDiagnosticVMOptions", diagnosticOption,
"Hello");
if (!TestCommon.isUnableToMap(output)) {
output.shouldHaveExitValue(0);
output.shouldContain(warningMessages[0]);
output.shouldContain(warningMessages[1]);
output.shouldContain("[class,load] Hello source: shared objects file");
}
// Using the archive with -Xshare:on without the diagnostic option.
// VM should exit with an error message.
output = TestCommon.exec(
appJar,
"Hello");
output.shouldHaveExitValue(1);
output.shouldContain(errorMessage);
// Using the archive with -Xshare:auto without the diagnostic option.
// VM should continue execution with a warning message. The archive
// will not be used.
output = TestCommon.execAuto(
"-cp", appJar,
"-Xlog:class+load=trace,cds=info",
"Hello");
if (!TestCommon.isUnableToMap(output)) {
output.shouldHaveExitValue(0);
output.shouldContain(errorMessage);
output.shouldMatch(".class.load. Hello source:.*DumpingWithJavaAgent.jar");
// CDS dumping with a java agent without the AllowArchvingWithJavaAgent diagnostic option.
// VM will exit with an error message.
output = TestCommon.dump(appJar, TestCommon.list("Hello"),
"-javaagent:" + agentJar);
}
output.shouldContain("Must enable AllowArchivingWithJavaAgent in order to run Java agent during CDS dumping")
.shouldHaveExitValue(1);
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary CDS dumping with JVMTI agent.
* @requires vm.cds
* @requires vm.flavor != "minimal"
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
* @modules jdk.jartool/sun.tools.jar
* @compile ../../test-classes/Hello.java
* @run main/othervm/native DumpingWithJvmtiAgent
*/
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import jdk.test.lib.process.OutputAnalyzer;
public class DumpingWithJvmtiAgent {
private static final String AGENT_LIB_ONLOAD = "AddToSystemCLSearchOnLoad";
public static void main(String[] args) throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
// CDS dump with a JVMTI agent with the AllowArchivingWithJavaAgent option.
// vm should exit with an error message.
OutputAnalyzer out = TestCommon.dump(
appJar,
TestCommon.list("Hello"),
"-XX:+UnlockDiagnosticVMOptions", "-XX:+AllowArchivingWithJavaAgent",
"-agentlib:" + AGENT_LIB_ONLOAD + "=" + appJar,
"-Djava.library.path=" + System.getProperty("java.library.path"));
out.shouldContain("CDS dumping does not support native JVMTI agent, name: " + AGENT_LIB_ONLOAD)
.shouldHaveExitValue(1);
// CDS dump with a JVMTI agent without the AllowArchivingWithJavaAgent option.
// vm should exit with an error message.
out = TestCommon.dump(
appJar,
TestCommon.list("Hello"),
"-agentlib:" + AGENT_LIB_ONLOAD + "=" + appJar,
"-Djava.library.path=" + System.getProperty("java.library.path"));
out.shouldContain("CDS dumping does not support native JVMTI agent, name: " + AGENT_LIB_ONLOAD)
.shouldHaveExitValue(1);
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.lang.instrument.Instrumentation;
public class SimpleAgent {
public static void premain(String agentArg, Instrumentation instrumentation) {
System.out.println("inside SimpleAgent");
}
}

View File

@ -0,0 +1,2 @@
Manifest-Version: 1.0
Premain-Class: SimpleAgent

View File

@ -0,0 +1,48 @@
/*
* 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <stdio.h>
#include <string.h>
#include <jvmti.h>
#ifdef __cplusplus
extern "C" {
#endif
static jvmtiEnv *jvmti = NULL;
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
int err = (*jvm)->GetEnv(jvm, (void**) &jvmti, JVMTI_VERSION_9);
if (err != JNI_OK) {
return JNI_ERR;
}
err = (*jvmti)->AddToSystemClassLoaderSearch(jvmti, (const char*)options);
if (err != JVMTI_ERROR_NONE) {
return JNI_ERR;
}
return JNI_OK;
}
#ifdef __cplusplus
}
#endif