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