From c5a0eb15babe0de30a7bee3480bb3f7020c6187b Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Mon, 28 Jul 2025 14:29:16 +0200 Subject: [PATCH] fix(environment): Exclude classpath from VM options --- .../java/datadog/environment/JvmOptions.java | 94 +++++++++---------- .../datadog/environment/JvmOptionsTest.java | 9 +- 2 files changed, 49 insertions(+), 54 deletions(-) diff --git a/components/environment/src/main/java/datadog/environment/JvmOptions.java b/components/environment/src/main/java/datadog/environment/JvmOptions.java index 6e5315f5a0b..e78ff890c31 100644 --- a/components/environment/src/main/java/datadog/environment/JvmOptions.java +++ b/components/environment/src/main/java/datadog/environment/JvmOptions.java @@ -40,57 +40,11 @@ private String[] readProcFsCmdLine() { return null; } - private List findVmOptions() { - return findVmOptions(PROCFS_CMDLINE); - } - @SuppressForbidden // Class.forName() as backup - // Visible for testing - List findVmOptions(String[] procfsCmdline) { + private List findVmOptions() { // Try ProcFS on Linux - // Be aware that when running a native image, the command line in /proc/self/cmdline is just the - // executable - if (procfsCmdline != null) { - // Create list of VM options - List vmOptions = new ArrayList<>(); - // Start at 1 to skip "java" command itself - int index = 1; - // Look for first self-standing argument that is not prefixed with "-" or end of VM options - // Skip "-jar" and the jar file - // Simultaneously, collect all arguments in the VM options - for (; index < procfsCmdline.length; index++) { - String argument = procfsCmdline[index]; - if (argument.startsWith("@")) { - vmOptions.addAll(getArgumentsFromFile(argument)); - } else { - if ("-jar".equals(argument)) { - // skip "-jar" and the jar file - index++; - continue; - } else if ("-cp".equals(argument)) { - // slurp '-cp' and the classpath - vmOptions.add(argument); - if (index + 1 < procfsCmdline.length) { - argument = procfsCmdline[++index]; - } - } else if (!argument.startsWith("-")) { - // end of VM options - break; - } - vmOptions.add(argument); - } - } - // Insert JDK_JAVA_OPTIONS at the start if present and supported - List jdkJavaOptions = getJdkJavaOptions(); - if (!jdkJavaOptions.isEmpty()) { - vmOptions.addAll(0, jdkJavaOptions); - } - // Insert JAVA_TOOL_OPTIONS at the start if present - List javaToolOptions = getJavaToolOptions(); - if (!javaToolOptions.isEmpty()) { - vmOptions.addAll(0, javaToolOptions); - } - return vmOptions; + if (PROCFS_CMDLINE != null) { + return findVmOptionsFromProcFs(PROCFS_CMDLINE); } // Try Oracle-based @@ -137,6 +91,48 @@ List findVmOptions(String[] procfsCmdline) { return emptyList(); } + // Be aware that when running a native image, the command line in /proc/self/cmdline is just the + // executable + // Visible for testing + List findVmOptionsFromProcFs(String[] procfsCmdline) { + // Create list of VM options + List vmOptions = new ArrayList<>(); + // Look for first self-standing argument that is not prefixed with "-" or end of VM options + // while simultaneously, collect all arguments in the VM options + // Starts from 1 as 0 is the java command itself (or native-image) + for (int index = 1; index < procfsCmdline.length; index++) { + String argument = procfsCmdline[index]; + // Inflate arg files + if (argument.startsWith("@")) { + vmOptions.addAll(getArgumentsFromFile(argument)); + } + // Skip classpath argument (not part of VM options) + else if ("-cp".equals(argument)) { + index++; + } + // Check "-jar" or class name argument as the end of the VM options + else if ("-jar".equals(argument) || !argument.startsWith("-")) { + // End of VM options + break; + } + // Otherwise add as VM option + else { + vmOptions.add(argument); + } + } + // Insert JDK_JAVA_OPTIONS at the start if present and supported + List jdkJavaOptions = getJdkJavaOptions(); + if (!jdkJavaOptions.isEmpty()) { + vmOptions.addAll(0, jdkJavaOptions); + } + // Insert JAVA_TOOL_OPTIONS at the start if present + List javaToolOptions = getJavaToolOptions(); + if (!javaToolOptions.isEmpty()) { + vmOptions.addAll(0, javaToolOptions); + } + return vmOptions; + } + private static List getArgumentsFromFile(String argFile) { String filename = argFile.substring(1); Path path = Paths.get(filename); diff --git a/components/environment/src/test/java/datadog/environment/JvmOptionsTest.java b/components/environment/src/test/java/datadog/environment/JvmOptionsTest.java index 3e07fc46ba5..3d66c562262 100644 --- a/components/environment/src/test/java/datadog/environment/JvmOptionsTest.java +++ b/components/environment/src/test/java/datadog/environment/JvmOptionsTest.java @@ -135,12 +135,12 @@ private static Stream procFsCmdLine() { arguments( "Java from class and options", new String[]{"java", "-Xmx512m", "-Xms256m", "-cp", "app.jar", "Main"}, - asList("-Xmx512m", "-Xms256m", "-cp", "app.jar") + asList("-Xmx512m", "-Xms256m") ), arguments( "Java from class and options, mixed", new String[]{"java", "-Xms256m", "-cp", "app.jar", "-Xmx512m", "Main"}, - asList("-Xms256m", "-cp", "app.jar", "-Xmx512m") + asList("-Xms256m", "-Xmx512m") ), arguments( "Args from file", @@ -167,10 +167,9 @@ private static Stream procFsCmdLine() { @ParameterizedTest(name = "[{index}] {0}") @MethodSource("procFsCmdLine") - void testFindVmOptionsWithProcFsCmdLine( - String useCase, String[] procfsCmdline, List expected) throws Exception { + void testFindVmOptionsFromProcFs(String useCase, String[] procfsCmdline, List expected) { JvmOptions vmOptions = new JvmOptions(); - List found = vmOptions.findVmOptions(procfsCmdline); + List found = vmOptions.findVmOptionsFromProcFs(procfsCmdline); assertEquals(expected, found); }