Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions make/TestImage.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ $(README):

TARGETS += $(BUILD_INFO_PROPERTIES) $(README)

# SapMachine 2025-08-11: Copy test jar for SAP JMC agent if needed.
ifeq ($(SAP_JMC_AGENT_ENABLED), true)
$(TEST_IMAGE_DIR)/jars/agent-tests.jar: $(SAP_JMC_AGENT_PATH)/agent-$(SAP_JMC_AGENT_VERSION)-tests.jar
$(call install-file)

TARGETS += $(TEST_IMAGE_DIR)/jars/agent-tests.jar
endif

################################################################################

prepare-test-image: $(TARGETS)
Expand Down
3 changes: 3 additions & 0 deletions make/autoconf/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ JDKOPT_SETUP_CODE_COVERAGE
# AddressSanitizer
JDKOPT_SETUP_ADDRESS_SANITIZER

# SapMachine 2024-12-05: Setup SAP JMC agent if requested
JDKOPT_SETUP_SAP_JMC_AGENT

# UndefinedBehaviorSanitizer
JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER

Expand Down
23 changes: 23 additions & 0 deletions make/autoconf/jdk-options.m4
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,29 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
AC_SUBST(SHIP_DEBUG_SYMBOLS)
])

# SapMachine 2025-08-11: import JMC agent jars
AC_DEFUN_ONCE([JDKOPT_SETUP_SAP_JMC_AGENT],
[
AC_ARG_WITH(sap-jmc-agent, [AS_HELP_STRING([--with-sap-jmc-agent],
[Set import path for the SAP JMC agent jars])])
SAP_JMC_AGENT_ENABLED=false
if test "x$with_sap_jmc_agent" != x; then
SAP_JMC_AGENT_PATH="$with_sap_jmc_agent"
UTIL_FIXUP_PATH(SAP_JMC_AGENT_PATH)
if test -f "$SAP_JMC_AGENT_PATH"/agent-*-boot.jar; then
SAP_JMC_AGENT_VERSION=$($BASENAME "$SAP_JMC_AGENT_PATH"/agent-*-boot.jar | $SED -e 's/^agent-//' -e 's/-boot.jar$//')
SAP_JMC_AGENT_ENABLED=true
JVM_CFLAGS="$JVM_CFLAGS -DWITH_SAP_JMC_AGENT=1"
AC_MSG_NOTICE([SAP JMC agent found at $SAP_JMC_AGENT_PATH, version $SAP_JMC_AGENT_VERSION])
else
AC_MSG_ERROR([SAP JMC agent was set, but the agent jars were not found])
fi
fi
AC_SUBST(SAP_JMC_AGENT_PATH)
AC_SUBST(SAP_JMC_AGENT_VERSION)
AC_SUBST(SAP_JMC_AGENT_ENABLED)
])

################################################################################
#
# Native and Java code coverage
Expand Down
5 changes: 5 additions & 0 deletions make/autoconf/spec.gmk.in
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@ UNLIMITED_CRYPTO=@UNLIMITED_CRYPTO@
ASYNC_PROFILER_IMPORT_PATH=@ASYNC_PROFILER_IMPORT_PATH@
ASYNC_PROFILER_IMPORT_ENABLED=@ASYNC_PROFILER_IMPORT_ENABLED@

# SapMachine 2025-08-11: import SAP JMC agent jars
SAP_JMC_AGENT_PATH=@SAP_JMC_AGENT_PATH@
SAP_JMC_AGENT_VERSION=@SAP_JMC_AGENT_VERSION@
SAP_JMC_AGENT_ENABLED=@SAP_JMC_AGENT_ENABLED@

GCOV_ENABLED=@GCOV_ENABLED@
JCOV_ENABLED=@JCOV_ENABLED@
JCOV_HOME=@JCOV_HOME@
Expand Down
11 changes: 11 additions & 0 deletions make/modules/java.base/Copy.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,14 @@ ifeq ($(call isTargetOs, linux macosx), true)
endif

################################################################################
# SapMachine 2025-08-11: Copy jmc agent jars
ifeq ($(SAP_JMC_AGENT_ENABLED), true)
$(LIB_DST_DIR)/agent.jar: $(SAP_JMC_AGENT_PATH)/agent-$(SAP_JMC_AGENT_VERSION).jar
$(call install-file)
$(LIB_DST_DIR)/agent-boot.jar: $(SAP_JMC_AGENT_PATH)/agent-$(SAP_JMC_AGENT_VERSION)-boot.jar
$(call install-file)

TARGETS += $(LIB_DST_DIR)/agent.jar $(LIB_DST_DIR)/agent-boot.jar
endif

################################################################################
23 changes: 23 additions & 0 deletions src/hotspot/share/runtime/arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2405,6 +2405,29 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m
}
}
#endif // !INCLUDE_JVMTI
// SapMachine 2025-08-11: Handle jmc agent if requested.
} else if (match_option(option, "-jmcagent:", &tail)) {
#if !defined(WITH_SAP_JMC_AGENT)
jio_fprintf(defaultStream::error_stream(),
"SAP JMC agent is not included in this VM\n");
return JNI_ERR;
#else
#if !INCLUDE_JVMTI
#error "Must have JVMTI enabled with SAP JVM agent"
#endif
char const* agent_jar = "agent.jar";
if (tail != nullptr) {
size_t length = strlen(tail) + strlen(_java_home->value()) + strlen(agent_jar) + 7;
char* options = NEW_C_HEAP_ARRAY(char, length, mtArguments);
jio_snprintf(options, length, "%s/lib/%s=%s", _java_home->value(), agent_jar, tail);
JvmtiAgentList::add("instrument", options, false);

// java agents need module java.instrument
if (!create_numbered_module_property("jdk.module.addmods", "java.instrument", addmods_count++)) {
return JNI_ENOMEM;
}
}
#endif // !WITH_SAP_JMC_AGENT
// --enable_preview
} else if (match_option(option, "--enable-preview")) {
set_enable_preview();
Expand Down
34 changes: 34 additions & 0 deletions src/hotspot/share/services/diagnosticCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ void DCmd::register_dcmds(){
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<EventLogDCmd>(full_export, true, false));
#if INCLUDE_JVMTI // Both JVMTI and SERVICES have to be enabled to have this dcmd
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIAgentLoadDCmd>(full_export, true, false));
// SapMachine 2025-08-11: Add support for SAP JMC agent if requested.
#if defined(WITH_SAP_JMC_AGENT)
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JVMTIJmcAgentLoadDCmd>(full_export, true, false));
#endif
#endif // INCLUDE_JVMTI
#endif // INCLUDE_SERVICES
#if INCLUDE_JVMTI
Expand Down Expand Up @@ -350,6 +354,36 @@ void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) {
}
}

// SapMachine 2025-08-11
#if defined(WITH_SAP_JMC_AGENT)
JVMTIJmcAgentLoadDCmd::JVMTIJmcAgentLoadDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_option("agent option", "Option string to pass the JMC agent.", "STRING", false) {
_dcmdparser.add_dcmd_argument(&_option);
}

void JVMTIJmcAgentLoadDCmd::execute(DCmdSource source, TRAPS) {
char const* java_home = Arguments::get_java_home();
char const* agent_jar = "agent.jar";
char const* option = _option.value();
size_t len = strlen(java_home) + strlen(agent_jar) + (option == nullptr ? 0 : 1 + strlen(option)) + 7;
char* agent_line = (char*)os::malloc(len, mtInternal);

if (agent_line == nullptr) {
output()->print_cr("JVMTI JMC agent attach failed: "
"Could not allocate " SIZE_FORMAT_X_0 " bytes for argument.",
len);
return;
}

jio_snprintf(agent_line, len, "%s/lib/%s%s%s", java_home, agent_jar, option == nullptr ? "" : "=",
option == nullptr ? "" : option);
JvmtiAgentList::load_agent("instrument", false, agent_line, output());

os::free(agent_line);
}
#endif // WITH_SAP_JMC_AGENT

#endif // INCLUDE_JVMTI
#endif // INCLUDE_SERVICES

Expand Down
25 changes: 25 additions & 0 deletions src/hotspot/share/services/diagnosticCommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,31 @@ class JVMTIAgentLoadDCmd : public DCmdWithParser {
}
virtual void execute(DCmdSource source, TRAPS);
};

// SapMachine 2025-08-11
#if defined(WITH_SAP_JMC_AGENT)
class JVMTIJmcAgentLoadDCmd : public DCmdWithParser {
protected:
DCmdArgument<char*> _option;
public:
JVMTIJmcAgentLoadDCmd(outputStream* output, bool heap);
static int num_arguments() { return 1; }
static const char* name() { return "JVMTI.jmc_agent_load"; }
static const char* description() {
return "Load the SAP jmc agent.";
}
static const char* impact() {
return "Medium: Depends on the command or trace";
}
static const JavaPermission permission() {
JavaPermission p = { "java.lang.management.ManagementPermission",
"control", nullptr };
return p;
}
virtual void execute(DCmdSource source, TRAPS);
};
#endif // WITH_SAP_JMC_AGENT

#endif // INCLUDE_JVMTI
#endif // INCLUDE_SERVICES

Expand Down
1 change: 1 addition & 0 deletions test/jdk/TEST.groups
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ tier1_sapmachine = \
java/net/Socket/ExceptionText.java \
java/util/jar/Manifest/IncludeInExceptionsTest.java \
jdk/security/JavaDotSecurity/TestJDKIncludeInExceptions.java \
sap \
sun/net/www/http/KeepAliveCache/TestConnectionIDFeature.java \
sun/security/lib/cacerts/VerifyCACerts.java \
tools/jlink/plugins/AddSapMachineToolsTest.java \
Expand Down
78 changes: 78 additions & 0 deletions test/jdk/sap/JmcAgentIntegrationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2025 SAP SE. 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 Runs the test for the jmc agent integration.
*
* @run main/othervm JmcAgentIntegrationTest
*/

import java.lang.reflect.Method;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;

public class JmcAgentIntegrationTest {

public static void main(String[] args) throws Exception {
File jar = new File(System.getenv("TEST_IMAGE_DIR") + "/jars/agent-tests.jar");

if (!jar.exists()) {
return; // Feature was not enabled.
}

ArrayList<String> testOptions = new ArrayList<>();
testOptions.add("-dump");

// Only run VM-agnostic tests if the ASM version we are using cannot handle the class file spec of this VM.
int spec = Integer.getInteger("java.vm.specification.version", 99999);
String javaHome = System.getProperty("java.home");
File agentJar = new File(javaHome + "/lib/agent.jar");
ClassLoader parentLoader = JmcAgentIntegrationTest.class.getClassLoader();
URLClassLoader agentLoader = new URLClassLoader(new URL[] {agentJar.toURI().toURL()}, parentLoader);
try {
Class.forName("org.openjdk.jmc.internal.org.objectweb.asm.Opcodes", true, agentLoader).getDeclaredField("V" + spec);
} catch (NoSuchFieldException e) {
System.out.println("Incompatible class file version. Skipping VM specific tests.");
testOptions.add("-vm-agnostic-tests");
}

URL url = jar.toURI().toURL();
String classPath = System.getProperty("java.class.path", ".");

System.setProperty("java.class.path", classPath + System.getProperty("path.separator") + jar.toString());
System.setProperty("useJmcAgentOption", "true");
System.setProperty("traceExecs", "true");

URLClassLoader cl = new URLClassLoader(new URL[] {url}, parentLoader);
Class<?> testClass = Class.forName("org.openjdk.jmc.agent.sap.test.TestRunner", true, cl);
Method mainMethod = testClass.getDeclaredMethod("main", String[].class, String[].class);
mainMethod.invoke(null, new Object[] {testOptions.toArray(new String[0]), new String[] {"-XX:+EnableDynamicAgentLoading"}});
}
}
Loading