diff --git a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java
index b8e775d4fb1..e5a625db7a7 100644
--- a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java
+++ b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java
@@ -192,10 +192,36 @@ public OpenJdkController(final ConfigProvider configProvider)
// Toggle settings from config
- if (configProvider.getBoolean(
- ProfilingConfig.PROFILING_HEAP_ENABLED, ProfilingConfig.PROFILING_HEAP_ENABLED_DEFAULT)) {
- log.debug("Enabling OldObjectSample JFR event with the config.");
- recordingSettings.put("jdk.OldObjectSample#enabled", "true");
+ // Unified live heap (profiling.heap.enabled): when explicitly disabled, turn off
+ // OldObjectSample. When enabled (or default), if ddprof is likely handling live heap,
+ // proactively disable OldObjectSample to avoid double collection.
+ // disableOverriddenEvents() at recording start is the definitive safety net,
+ // but we disable here too so the settings map is consistent from the start.
+ if (!configProvider.getBoolean(
+ ProfilingConfig.PROFILING_HEAP_ENABLED, isLiveHeapProfilingSafe())) {
+ disableEvent(recordingSettings, "jdk.OldObjectSample", "live heap profiling is disabled");
+ } else {
+ // ddprof live heap requires Java 11+ (JVMTI Allocation Sampler)
+ // isJmethodIDSafe() matches ddprof's own default for liveheap: it only enables
+ // MEMLEAK mode by default on versions where jmethodID is safe.
+ boolean ddprofLikelyActive =
+ isJavaVersionAtLeast(11)
+ && configProvider.getBoolean(
+ ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED, isJmethodIDSafe())
+ && configProvider.getBoolean(
+ ProfilingConfig.PROFILING_DATADOG_PROFILER_ENABLED, true);
+ if (ddprofLikelyActive) {
+ disableEvent(
+ recordingSettings,
+ "jdk.OldObjectSample",
+ "ddprof live heap profiling is expected to handle live heap data");
+ } else if (isOldObjectSampleAvailable()) {
+ enableEvent(recordingSettings, "jdk.OldObjectSample", "heap profiling is enabled");
+ } else if (configProvider.getBoolean(ProfilingConfig.PROFILING_HEAP_ENABLED, false)) {
+ log.warn(
+ "Live heap profiling was explicitly requested but is not supported on this JVM version;"
+ + " no heap profiling data will be collected.");
+ }
}
if (configProvider.getBoolean(
@@ -240,9 +266,8 @@ ProfilingConfig.PROFILING_ALLOCATION_ENABLED, isObjectAllocationSampleAvailable(
// Warn users for expensive events
- if (!isOldObjectSampleAvailable()
- && isEventEnabled(recordingSettings, "jdk.OldObjectSample#enabled")) {
- log.warn("Inexpensive heap profiling is not supported for this JDK but is enabled.");
+ if (!isOldObjectSampleAvailable() && isEventEnabled(recordingSettings, "jdk.OldObjectSample")) {
+ log.warn("JFR based live heap profiling is not supported for this JDK but is enabled.");
}
if (isEventEnabled(recordingSettings, "jdk.ObjectAllocationInNewTLAB")
diff --git a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java
index 3d90c346417..ef853d07b9a 100644
--- a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java
+++ b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java
@@ -16,9 +16,11 @@
import com.datadog.profiling.controller.ControllerContext;
import com.datadog.profiling.controller.jfr.JfpUtilsTest;
+import com.datadog.profiling.utils.ProfilingMode;
import datadog.environment.JavaVirtualMachine;
import datadog.trace.api.profiling.RecordingData;
import datadog.trace.bootstrap.config.provider.ConfigProvider;
+import java.util.EnumSet;
import java.util.Properties;
import jdk.jfr.Recording;
import org.junit.jupiter.api.BeforeAll;
@@ -94,6 +96,8 @@ public void testHeapProfilerIsStillOverriddenOnUnsupportedVersion() throws Excep
public void testHeapProfilerIsStillOverriddenThroughConfig() throws Exception {
Properties props = getConfigProperties();
props.put(PROFILING_HEAP_ENABLED, "true");
+ // Disable ddprof so OldObjectSample is not proactively disabled
+ props.put(PROFILING_DATADOG_PROFILER_ENABLED, "false");
ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props);
@@ -102,10 +106,11 @@ public void testHeapProfilerIsStillOverriddenThroughConfig() throws Exception {
((OpenJdkRecordingData)
controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop())
.getRecording()) {
- if (!isOldObjectSampleAvailable()) {
- assertEquals(
- true, Boolean.parseBoolean(recording.getSettings().get("jdk.OldObjectSample#enabled")));
- }
+ // On JVMs where OldObjectSample is not available (e.g. Java 8), explicitly enabling heap
+ // profiling has no effect — the event cannot be safely enabled.
+ assertEquals(
+ isOldObjectSampleAvailable(),
+ Boolean.parseBoolean(recording.getSettings().get("jdk.OldObjectSample#enabled")));
}
}
@@ -234,6 +239,43 @@ public void testNativeProfilerIsStillOverriddenOnUnsupportedVersion() throws Exc
}
}
+ @Test
+ public void testOldObjectSampleDisabledWhenDdprofMemleakActive() throws Exception {
+ Properties props = getConfigProperties();
+ props.put(PROFILING_DATADOG_PROFILER_ENABLED, "true");
+
+ ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props);
+
+ ControllerContext context = new ControllerContext();
+ context.setDatadogProfilerEnabled(true);
+ context.setDatadogProfilingModes(EnumSet.of(ProfilingMode.MEMLEAK));
+
+ OpenJdkController controller = new OpenJdkController(configProvider);
+ try (final Recording recording =
+ ((OpenJdkRecordingData) controller.createRecording(TEST_NAME, context.snapshot()).stop())
+ .getRecording()) {
+ assertFalse(Boolean.parseBoolean(recording.getSettings().get("jdk.OldObjectSample#enabled")));
+ }
+ }
+
+ @Test
+ public void testUnifiedFlagDisabledTurnsOffOldObjectSample() throws Exception {
+ Properties props = getConfigProperties();
+ props.put(PROFILING_HEAP_ENABLED, "false");
+
+ ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props);
+
+ OpenJdkController controller = new OpenJdkController(configProvider);
+ RecordingData data =
+ controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop();
+ assertTrue(data instanceof OpenJdkRecordingData);
+ try (final Recording recording = ((OpenJdkRecordingData) data).getRecording()) {
+ assertFalse(
+ Boolean.parseBoolean(recording.getSettings().get("jdk.OldObjectSample#enabled")),
+ "OldObjectSample should be disabled when unified live heap flag is false");
+ }
+ }
+
private static Properties getConfigProperties() {
Properties props = new Properties();
// make sure the async profiler is not force-enabled
diff --git a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java
index 6488af7f6e2..95f538a715c 100644
--- a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java
+++ b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java
@@ -157,12 +157,19 @@ private String getProfilerConfig() {
ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT);
sb.append("\n=== Heap Profiling ===\n");
+ boolean heapDefault = ProfilingSupport.isLiveHeapProfilingSafe();
appendConfig(
sb,
"Heap Profiling Enabled",
- configProvider.getBoolean(
- ProfilingConfig.PROFILING_HEAP_ENABLED, ProfilingConfig.PROFILING_HEAP_ENABLED_DEFAULT),
- ProfilingConfig.PROFILING_HEAP_ENABLED_DEFAULT);
+ configProvider.getBoolean(ProfilingConfig.PROFILING_HEAP_ENABLED, heapDefault),
+ heapDefault);
+ appendConfig(
+ sb,
+ "DDProf Live Heap Enabled",
+ configProvider.getString(ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED),
+ null);
+ appendConfig(
+ sb, "JFR OldObjectSample Available", ProfilingSupport.isOldObjectSampleAvailable(), false);
appendConfig(
sb,
"Heap Histogram Enabled",
diff --git a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java
index d2a1d1e81e7..a60e6b8f1dc 100644
--- a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java
+++ b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java
@@ -140,7 +140,7 @@ protected ProfilerSettingsSupport(
ProfilingSupport.isObjectAllocationSampleAvailable());
heapProfilingEnabled =
configProvider.getBoolean(
- ProfilingConfig.PROFILING_HEAP_ENABLED, ProfilingConfig.PROFILING_HEAP_ENABLED_DEFAULT);
+ ProfilingConfig.PROFILING_HEAP_ENABLED, ProfilingSupport.isLiveHeapProfilingSafe());
startForceFirst =
configProvider.getBoolean(
ProfilingConfig.PROFILING_START_FORCE_FIRST,
diff --git a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilingSupport.java b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilingSupport.java
index cac2a4c506f..fc1a480795f 100644
--- a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilingSupport.java
+++ b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilingSupport.java
@@ -4,8 +4,41 @@
import static datadog.environment.JavaVirtualMachine.isJavaVersionAtLeast;
import static datadog.environment.JavaVirtualMachine.isOracleJDK8;
+import datadog.environment.JavaVirtualMachine;
+
public class ProfilingSupport {
+ /**
+ * Checks whether jmethodID handling is safe on the current JVM version. Unsafe versions can cause
+ * crashes due to JDK-8313816.
+ */
+ public static boolean isJmethodIDSafe() {
+ if (isJavaVersionAtLeast(22)) {
+ return true;
+ }
+ switch (JavaVirtualMachine.getLangVersion()) {
+ case "8":
+ return true;
+ case "11":
+ return isJavaVersionAtLeast(11, 0, 23);
+ case "17":
+ return isJavaVersionAtLeast(17, 0, 11);
+ case "21":
+ return isJavaVersionAtLeast(21, 0, 3);
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Checks whether any live heap profiling mechanism is safe to enable on the current platform.
+ * Returns true if at least one of ddprof native (jmethodID safe) or JFR OldObjectSample is
+ * available.
+ */
+ public static boolean isLiveHeapProfilingSafe() {
+ return isJmethodIDSafe() || isOldObjectSampleAvailable();
+ }
+
public static boolean isOldObjectSampleAvailable() {
if (isOracleJDK8()) {
return false;
diff --git a/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java b/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java
index 4abbe9520c7..60c0d5c2e60 100644
--- a/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java
+++ b/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java
@@ -1,5 +1,6 @@
package com.datadog.profiling.ddprof;
+import static com.datadog.profiling.controller.ProfilingSupport.isOldObjectSampleAvailable;
import static datadog.environment.JavaVirtualMachine.isJ9;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_ALLOCATION_ENABLED;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_CONTEXT_ATTRIBUTES;
@@ -20,7 +21,6 @@
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_CAPACITY;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_CAPACITY_DEFAULT;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED;
-import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED_DEFAULT;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_INTERVAL;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_SAMPLE_PERCENT;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_SAMPLE_PERCENT_DEFAULT;
@@ -43,6 +43,7 @@
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_WALL_ENABLED;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_WALL_INTERVAL;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_WALL_INTERVAL_DEFAULT;
+import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_ENABLED;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_TRACK_GENERATIONS;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_TRACK_GENERATIONS_DEFAULT;
import static datadog.trace.api.config.ProfilingConfig.PROFILING_QUEUEING_TIME_ENABLED;
@@ -52,6 +53,7 @@
import static datadog.trace.api.config.ProfilingConfig.PROFILING_ULTRA_MINIMAL;
import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ENABLED;
+import com.datadog.profiling.controller.ProfilingSupport;
import datadog.environment.JavaVirtualMachine;
import datadog.trace.api.config.ProfilingConfig;
import datadog.trace.bootstrap.config.provider.ConfigProvider;
@@ -165,26 +167,12 @@ public static boolean getWallContextFilter(ConfigProvider configProvider) {
PROFILING_DATADOG_PROFILER_WALL_CONTEXT_FILTER_DEFAULT);
}
- private static boolean isJmethodIDSafe() {
- // see https://bugs.openjdk.org/browse/JDK-8313816
- if (JavaVirtualMachine.isJavaVersionAtLeast(22)) {
- // any version after 22 should be safe
- return true;
- }
- switch (JavaVirtualMachine.getLangVersion()) {
- case "8":
- // Java 8 is not affected by the jmethodID issue
- return true;
- case "11":
- return JavaVirtualMachine.isJavaVersionAtLeast(11, 0, 23);
- case "17":
- return JavaVirtualMachine.isJavaVersionAtLeast(17, 0, 11);
- case "21":
- return JavaVirtualMachine.isJavaVersionAtLeast(21, 0, 3);
- default:
- // any other non-LTS version should be considered unsafe
- return false;
- }
+ static boolean isJmethodIDSafe() {
+ return ProfilingSupport.isJmethodIDSafe();
+ }
+
+ static boolean isMemoryLeakProfilingSafe() {
+ return ProfilingSupport.isLiveHeapProfilingSafe();
}
public static boolean isAllocationProfilingEnabled(ConfigProvider configProvider) {
@@ -223,16 +211,29 @@ public static int getAllocationInterval() {
}
public static boolean isMemoryLeakProfilingEnabled(ConfigProvider configProvider) {
- boolean isSafe = isJmethodIDSafe();
+ boolean unifiedEnabled =
+ configProvider.getBoolean(PROFILING_HEAP_ENABLED, isMemoryLeakProfilingSafe());
+ if (!unifiedEnabled) {
+ return false;
+ }
+ // JVMTI Allocation Sampler is required for ddprof live heap and is available since Java 11.
+ // isJmethodIDSafe() alone is not sufficient — Java 8 is jmethodID-safe but lacks the sampler.
+ boolean isSafe = JavaVirtualMachine.isJavaVersionAtLeast(11) && isJmethodIDSafe();
boolean enableDdprofMemleak =
getBoolean(
configProvider,
PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED,
- PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED_DEFAULT,
+ isSafe,
PROFILING_DATADOG_PROFILER_MEMLEAK_ENABLED);
if (!isSafe && enableDdprofMemleak) {
log.warn(
- "Memory leak profiling was enabled although it is not considered stable on this JVM version.");
+ "Live heap profiling (ddprof) was enabled although it is not considered stable"
+ + " on this JVM version.");
+ }
+ if (!enableDdprofMemleak && !isOldObjectSampleAvailable()) {
+ log.warn(
+ "ddprof live heap profiling is disabled and JFR OldObjectSample is not available"
+ + " on this JVM. Live heap profiling will be inactive.");
}
return enableDdprofMemleak;
}
diff --git a/dd-java-agent/agent-profiling/profiling-ddprof/src/test/java/com/datadog/profiling/ddprof/DatadogProfilerConfigTest.java b/dd-java-agent/agent-profiling/profiling-ddprof/src/test/java/com/datadog/profiling/ddprof/DatadogProfilerConfigTest.java
index b7a07fbb5a2..ed4b4476606 100644
--- a/dd-java-agent/agent-profiling/profiling-ddprof/src/test/java/com/datadog/profiling/ddprof/DatadogProfilerConfigTest.java
+++ b/dd-java-agent/agent-profiling/profiling-ddprof/src/test/java/com/datadog/profiling/ddprof/DatadogProfilerConfigTest.java
@@ -1,13 +1,18 @@
package com.datadog.profiling.ddprof;
+import static com.datadog.profiling.controller.ProfilingSupport.isOldObjectSampleAvailable;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import datadog.environment.JavaVirtualMachine;
import datadog.trace.api.config.ProfilingConfig;
import datadog.trace.bootstrap.config.provider.ConfigProvider;
import java.util.Properties;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -126,4 +131,70 @@ private static Stream hotspotStackwalkerTestCases() {
Arguments.of("lbr", "lbr"),
Arguments.of("no", "no"));
}
+
+ @Test
+ void isMemoryLeakProfilingSafeConsistentWithComponentChecks() {
+ boolean expected = DatadogProfilerConfig.isJmethodIDSafe() || isOldObjectSampleAvailable();
+ assertEquals(expected, DatadogProfilerConfig.isMemoryLeakProfilingSafe());
+ }
+
+ @Test
+ void unifiedFlagEnabledDdprofKeyDefaultReflectsSafety() {
+ Properties props = new Properties();
+ props.put(ProfilingConfig.PROFILING_HEAP_ENABLED, "true");
+ ConfigProvider config = ConfigProvider.withPropertiesOverride(props);
+ // ddprof live heap requires Java 11+ (JVMTI Allocation Sampler) AND jmethodID safety
+ boolean expectedDefault =
+ JavaVirtualMachine.isJavaVersionAtLeast(11) && DatadogProfilerConfig.isJmethodIDSafe();
+ assertEquals(expectedDefault, DatadogProfilerConfig.isMemoryLeakProfilingEnabled(config));
+ }
+
+ @Test
+ void unifiedFlagDisabledOverridesDdprof() {
+ Properties props = new Properties();
+ props.put(ProfilingConfig.PROFILING_HEAP_ENABLED, "false");
+ props.put(ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED, "true");
+ ConfigProvider config = ConfigProvider.withPropertiesOverride(props);
+ assertFalse(DatadogProfilerConfig.isMemoryLeakProfilingEnabled(config));
+ }
+
+ @Test
+ void unifiedFlagEnabledDdprofKeyDisabledReturnsFalse() {
+ Properties props = new Properties();
+ props.put(ProfilingConfig.PROFILING_HEAP_ENABLED, "true");
+ props.put(ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED, "false");
+ ConfigProvider config = ConfigProvider.withPropertiesOverride(props);
+ assertFalse(DatadogProfilerConfig.isMemoryLeakProfilingEnabled(config));
+ }
+
+ @Test
+ void unifiedFlagEnabledDdprofKeyEnabledReturnsTrue() {
+ Properties props = new Properties();
+ props.put(ProfilingConfig.PROFILING_HEAP_ENABLED, "true");
+ props.put(ProfilingConfig.PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED, "true");
+ ConfigProvider config = ConfigProvider.withPropertiesOverride(props);
+ assertTrue(DatadogProfilerConfig.isMemoryLeakProfilingEnabled(config));
+ }
+
+ @Test
+ void oldMemleakAliasStillWorks() {
+ Properties props = new Properties();
+ props.put(ProfilingConfig.PROFILING_HEAP_ENABLED, "true");
+ props.put(ProfilingConfig.PROFILING_DATADOG_PROFILER_MEMLEAK_ENABLED, "true");
+ ConfigProvider config = ConfigProvider.withPropertiesOverride(props);
+ assertTrue(DatadogProfilerConfig.isMemoryLeakProfilingEnabled(config));
+ }
+
+ @Test
+ void defaultBehaviorNoFlagsSetUsesAutoDetection() {
+ Properties props = new Properties();
+ ConfigProvider config = ConfigProvider.withPropertiesOverride(props);
+ // With no flags set:
+ // unified default = isMemoryLeakProfilingSafe()
+ // ddprof default = Java 11+ && isJmethodIDSafe()
+ // result = isMemoryLeakProfilingSafe() && (Java 11+ && isJmethodIDSafe())
+ boolean expectedDefault =
+ JavaVirtualMachine.isJavaVersionAtLeast(11) && DatadogProfilerConfig.isJmethodIDSafe();
+ assertEquals(expectedDefault, DatadogProfilerConfig.isMemoryLeakProfilingEnabled(config));
+ }
}
diff --git a/dd-smoke-tests/profiling-integration-tests/build.gradle b/dd-smoke-tests/profiling-integration-tests/build.gradle
index cdab8646de2..74fe60e6b82 100644
--- a/dd-smoke-tests/profiling-integration-tests/build.gradle
+++ b/dd-smoke-tests/profiling-integration-tests/build.gradle
@@ -27,6 +27,7 @@ dependencies {
implementation 'org.xerial.snappy:snappy-java:1.1.8.4'
testImplementation project(':dd-smoke-tests')
+ testImplementation project(':dd-java-agent:agent-profiling:profiling-controller')
testImplementation project(':dd-java-agent:agent-profiling:profiling-testing')
testImplementation libs.bundles.junit5
testImplementation libs.bundles.mockito
diff --git a/dd-smoke-tests/profiling-integration-tests/src/test/java/datadog/smoketest/JFRBasedProfilingIntegrationTest.java b/dd-smoke-tests/profiling-integration-tests/src/test/java/datadog/smoketest/JFRBasedProfilingIntegrationTest.java
index 25f8e1454c1..452cea370d8 100644
--- a/dd-smoke-tests/profiling-integration-tests/src/test/java/datadog/smoketest/JFRBasedProfilingIntegrationTest.java
+++ b/dd-smoke-tests/profiling-integration-tests/src/test/java/datadog/smoketest/JFRBasedProfilingIntegrationTest.java
@@ -1,5 +1,6 @@
package datadog.smoketest;
+import static com.datadog.profiling.controller.ProfilingSupport.isOldObjectSampleAvailable;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -700,6 +701,8 @@ private void assertRecordingEvents(
assertEquals(
JavaVirtualMachine.isJavaVersionAtLeast(11),
events.apply(ItemFilters.type("datadog.ObjectSample")).hasItems());
+ // Check live heap events
+ // ddprof is active — jdk.OldObjectSample should NOT be present since ddprof takes over
// TODO ddprof (async) profiler seems to be having some issues with stack depth limit and
// native frames
} else {
@@ -714,6 +717,12 @@ private void assertRecordingEvents(
assertTrue(stackTrace.getFrames().size() <= STACK_DEPTH_LIMIT);
}
}
+ // Check JFR live heap events
+ if (isOldObjectSampleAvailable()) {
+ assertTrue(
+ events.apply(ItemFilters.type("jdk.OldObjectSample")).hasItems(),
+ "Expected jdk.OldObjectSample events on JFR-only mode with supported JVM");
+ }
}
// check exception events