diff --git a/dd-java-agent/agent-profiling/profiling-uploader/src/main/java/com/datadog/profiling/uploader/util/JfrCliHelper.java b/dd-java-agent/agent-profiling/profiling-uploader/src/main/java/com/datadog/profiling/uploader/util/JfrCliHelper.java index 9668dc61d72..2178e486052 100644 --- a/dd-java-agent/agent-profiling/profiling-uploader/src/main/java/com/datadog/profiling/uploader/util/JfrCliHelper.java +++ b/dd-java-agent/agent-profiling/profiling-uploader/src/main/java/com/datadog/profiling/uploader/util/JfrCliHelper.java @@ -2,6 +2,7 @@ import static datadog.trace.util.AgentThreadFactory.AgentThread.PROFILER_HTTP_DISPATCHER; +import datadog.trace.api.Platform; import datadog.trace.api.profiling.RecordingData; import datadog.trace.relocate.api.IOLogger; import datadog.trace.util.AgentThreadFactory; @@ -44,7 +45,7 @@ public static void invokeOn(final RecordingData data, final IOLogger ioLogger) { File tmp = null; try { Path jfr = Paths.get(System.getProperty("java.home"), "bin", "jfr"); - if (!Files.exists(jfr)) { + if (Platform.isJ9() || !Files.exists(jfr)) { ioLogger.error("Failed to gather information on recording, can't find `jfr`"); return; } diff --git a/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/ProfileUploaderTest.java b/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/ProfileUploaderTest.java index fd7857b86ff..3edb3764c50 100644 --- a/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/ProfileUploaderTest.java +++ b/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/ProfileUploaderTest.java @@ -42,6 +42,7 @@ import datadog.common.version.VersionInfo; import datadog.trace.api.Config; import datadog.trace.api.DDTags; +import datadog.trace.api.Platform; import datadog.trace.api.profiling.ProfilingSnapshot; import datadog.trace.api.profiling.RecordingData; import datadog.trace.api.profiling.RecordingInputStream; @@ -561,7 +562,10 @@ public void test413Response() throws Exception { verify(recording).release(); - if (Files.exists(Paths.get(System.getProperty("java.home"), "bin", "jfr"))) { + // J9 has 'almost' implemented JFR, but not really + // we need to skip this part for J9 + if (!Platform.isJ9() + && Files.exists(Paths.get(System.getProperty("java.home"), "bin", "jfr"))) { verify(ioLogger) .error( eq("Failed to upload profile, it's too big. Dumping information about the profile")); diff --git a/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/util/JfrCliHelperTest.java b/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/util/JfrCliHelperTest.java index a8d2c1fd7a1..7c1faa3695d 100644 --- a/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/util/JfrCliHelperTest.java +++ b/dd-java-agent/agent-profiling/profiling-uploader/src/test/java/com/datadog/profiling/uploader/util/JfrCliHelperTest.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; +import datadog.trace.api.Platform; import datadog.trace.api.profiling.RecordingData; import datadog.trace.api.profiling.RecordingInputStream; import datadog.trace.relocate.api.IOLogger; @@ -24,6 +25,7 @@ import java.util.Set; import java.util.zip.GZIPOutputStream; import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -44,6 +46,9 @@ public class JfrCliHelperTest { @Test public void testInvokeOn() throws Exception { + // J9 may have 'jfr' command present but it requires additional setup + // Currently we don't support J9 JFR so we can safely skip this test + Assumptions.assumeFalse(Platform.isJ9()); final RecordingData recording = mockRecordingData(); JfrCliHelper.invokeOn(recording, ioLogger); diff --git a/dd-java-agent/agent-profiling/src/main/java/com/datadog/profiling/agent/CompositeController.java b/dd-java-agent/agent-profiling/src/main/java/com/datadog/profiling/agent/CompositeController.java index c221647c0d7..efcebce2a06 100644 --- a/dd-java-agent/agent-profiling/src/main/java/com/datadog/profiling/agent/CompositeController.java +++ b/dd-java-agent/agent-profiling/src/main/java/com/datadog/profiling/agent/CompositeController.java @@ -153,8 +153,11 @@ public static Controller build(ConfigProvider provider, ControllerContext contex } if (!isOracleJDK8) { try { - Class.forName("jdk.jfr.Event"); - controllers.add(OpenJdkController.instance(provider)); + if (Platform.hasJfr()) { + controllers.add(OpenJdkController.instance(provider)); + } else { + log.debug("JFR is not available on this platform"); + } } catch (Throwable ignored) { log.debug("Failed to load openjdk profiler", ignored); } diff --git a/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy b/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy index 87c30a4e684..f29fd7a859a 100644 --- a/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy +++ b/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy @@ -3,6 +3,7 @@ import datadog.trace.agent.test.AgentTestRunner import datadog.trace.agent.test.SpockRunner import datadog.trace.agent.test.utils.ClasspathUtils import datadog.trace.api.GlobalTracer +import datadog.trace.api.Platform import datadog.trace.bootstrap.Constants import datadog.trace.bootstrap.instrumentation.api.AgentScope import datadog.trace.bootstrap.instrumentation.api.AgentSpan @@ -180,11 +181,6 @@ class AgentTestRunnerTest extends AgentTestRunner { } boolean isJFRSupported() { - try { - Class.forName("jdk.jfr.Recording") - return true - } catch (Throwable e) { - return false - } + return Platform.hasJfr() } } diff --git a/internal-api/src/main/java/datadog/trace/api/Platform.java b/internal-api/src/main/java/datadog/trace/api/Platform.java index f14eac480bd..c1ed2b539d0 100644 --- a/internal-api/src/main/java/datadog/trace/api/Platform.java +++ b/internal-api/src/main/java/datadog/trace/api/Platform.java @@ -39,10 +39,13 @@ private static boolean checkForJfr() { /* Check only for the open-sources JFR implementation. * If it is ever needed to support also the closed sourced JDK 8 version the check should be * enhanced. - * Need this custom check because ClassLoaderMatchers.hasClassNamed() does not support bootstrap class loader yet. - * Note: the downside of this is that we load some JFR classes at startup. + * Note: we need to hardcode the good-known-versions instead of probing for JFR classes to + * make this work with GraalVM native image. + * Note: as of version 0.49.0 of J9 the JVM contains JFR classes, but it is not fully functional */ - return ClassLoader.getSystemClassLoader().getResource("jdk/jfr/Event.class") != null; + return ((isJavaVersion(8) && isJavaVersionAtLeast(8, 0, 272) || (isJavaVersionAtLeast(11)))) + && !isJ9() + && !isOracleJDK8(); } catch (Throwable e) { return false; }