From c4ad0ed8db0fe2ba944b749111612b54c28177e0 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 13:11:48 -0400 Subject: [PATCH 01/24] Support GitLab test execution on Linux arm64. --- .gitlab-ci.yml | 193 ++++++++++++++++++ build.gradle.kts | 19 ++ .../datadog/gradle/plugin/HostPlatform.kt | 21 ++ .../msgpack/MsgPackWriterTest.java | 3 +- .../datadog/environment/OperatingSystem.java | 10 + .../java/datadog/json/JsonReaderTest.java | 3 +- .../BuildIdExtractorIntegrationTest.java | 3 +- .../controller/EnvironmentChecker.java | 8 +- .../aerospike4/AerospikeBaseTest.groovy | 20 +- .../src/test/groovy/PubSubTest.groovy | 8 +- .../RemoteJDBCInstrumentationTest.groovy | 23 ++- .../instrumentation/protobuf-3.0/build.gradle | 27 ++- .../smoketest/AbstractSmokeTest.groovy | 7 + .../smoketest/WebSphereJmxSmokeTest.groovy | 7 + 14 files changed, 317 insertions(+), 35 deletions(-) create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/HostPlatform.kt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 369aa9b69c7..df5e8f5014a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,6 +38,7 @@ stages: - benchmarks - macrobenchmarks - tests + - tests-arm64 - test-summary - exploration-tests - ci-visibility-tests @@ -54,6 +55,8 @@ variables: GRADLE_VERSION: "8.14.4" # must match gradle-wrapper.properties MAVEN_REPOSITORY_PROXY: "https://depot-read-api-java.us1.ddbuild.io/magicmirror/magicmirror/@current/" GRADLE_PLUGIN_PROXY: "https://depot-read-api-java.us1.ddbuild.io/magicmirror/magicmirror/@current/" + ARM64_BUILDER_IMAGE_REPO: "registry.ddbuild.io/images/mirror/dd-trace-java-docker-build" + ARM64_BUILDER_IMAGE_TAG: "alexeyk_arm64-test-arm64-base" BUILDER_IMAGE_REPO: "registry.ddbuild.io/images/mirror/dd-trace-java-docker-build" # images are pinned in images/mirror.lock.yaml in the DataDog/images repo BUILDER_IMAGE_VERSION_PREFIX: "ci-" # use either an empty string (e.g. "") for latest images or a version followed by a hyphen (e.g. "ci-" or "123_merge-") REPO_NOTIFICATION_CHANNEL: "#apm-java-escalations" @@ -683,6 +686,123 @@ muzzle-dep-report: - scheduler_failure - data_integrity_failure +.test_job_arm64: + image: ${ARM64_BUILDER_IMAGE_REPO}:${ARM64_BUILDER_IMAGE_TAG} + tags: [ "docker-in-docker:arm64" ] + stage: tests-arm64 + needs: [] + variables: + # arm64 docker image installs only these JVMs; override the global default regex. + DEFAULT_TEST_JVMS: /^(8|11|17|21|25)$/ + GRADLE_PARAMS: "-PskipFlakyTests" + GRADLE_WORKERS: 6 + GRADLE_MEMORY_MIN: 1G + GRADLE_MEMORY_MAX: 4G + # Sized for the arm64 microvm runner pool (smaller than amd64). + # Observed peak on equivalent amd64 workload: ~14.5 GB / ~1.5 vCPU avg. + # Bump back up if jobs OOM or we see CPU throttling in cgroup-info. + KUBERNETES_CPU_REQUEST: 6 + KUBERNETES_MEMORY_REQUEST: 12Gi + KUBERNETES_MEMORY_LIMIT: 16Gi + TESTCONTAINERS_CHECKS_DISABLE: "true" + TESTCONTAINERS_RYUK_DISABLED: "true" + TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX: "registry.ddbuild.io/images/mirror/" + JETTY_AVAILABLE_PROCESSORS: 4 + GIT_SUBMODULE_STRATEGY: normal + GIT_SUBMODULE_DEPTH: 1 + rules: + - if: $testJvm =~ $DEFAULT_TEST_JVMS + when: manual + allow_failure: true + cache: + - key: dependency-$CACHE_TYPE + paths: + - .gradle/wrapper + - .gradle/caches + - .gradle/notifications + - .mvn/caches + policy: pull + fallback_keys: + - dependency-base + - dependency-lib + unprotect: true + before_script: + - git config --global --add safe.directory "$CI_PROJECT_DIR" + - export ORG_GRADLE_PROJECT_mavenRepositoryProxy=$MAVEN_REPOSITORY_PROXY + - export ORG_GRADLE_PROJECT_gradlePluginProxy=$GRADLE_PLUGIN_PROXY + - | + JAVA_HOMES=$(env | grep -E '^JAVA_[A-Z0-9_]+_HOME=' | sed 's/=.*//' | paste -sd,) + cat >> gradle.properties <()) } + // Temurin 11/21 on Linux arm64 SIGSEGVs in SystemDictionary::define_instance_class + // during CDS shared-class restore. GRADLE_OPTS / org.gradle.jvmargs only reaches the + // Gradle daemon, so every forked JVM (Test executor, JavaCompile worker daemon when + // the toolchain differs from the daemon's JDK) must disable CDS on its own. + val isLinuxArm64 = HostPlatform.isLinuxArm64() + tasks.configureEach { if (this is JavaForkOptions) { maxHeapSize = System.getProperty("datadog.forkedMaxHeapSize") @@ -91,6 +98,18 @@ allprojects { "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/tmp" ) + if (isLinuxArm64) { + jvmArgs("-Xshare:off") + } + } + } + + if (isLinuxArm64) { + tasks.withType().configureEach { + options.forkOptions.jvmArgs?.add("-Xshare:off") + } + tasks.withType().configureEach { + groovyOptions.forkOptions.jvmArgs?.add("-Xshare:off") } } } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/HostPlatform.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/HostPlatform.kt new file mode 100644 index 00000000000..40837194ecd --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/HostPlatform.kt @@ -0,0 +1,21 @@ +package datadog.gradle.plugin + +import java.util.Locale + +object HostPlatform { + @JvmStatic + fun isLinuxArm64(): Boolean = isExpectedOs("linux") && isArm64() + + @JvmStatic + fun isMacArm64(): Boolean = isExpectedOs("mac") && isArm64() + + private fun isExpectedOs(expectedOs: String): Boolean { + val osName = System.getProperty("os.name", "").lowercase(Locale.ROOT) + return osName.contains(expectedOs) + } + + private fun isArm64(): Boolean { + val osArch = System.getProperty("os.arch", "").lowercase(Locale.ROOT) + return osArch.contains("aarch64") || osArch.contains("arm64") + } +} diff --git a/communication/src/test/java/datadog/communication/serialization/msgpack/MsgPackWriterTest.java b/communication/src/test/java/datadog/communication/serialization/msgpack/MsgPackWriterTest.java index 4a3f773fdc5..fca302dd3d1 100644 --- a/communication/src/test/java/datadog/communication/serialization/msgpack/MsgPackWriterTest.java +++ b/communication/src/test/java/datadog/communication/serialization/msgpack/MsgPackWriterTest.java @@ -33,8 +33,7 @@ import org.msgpack.core.MessageUnpacker; public class MsgPackWriterTest { - // Explicit escapes for non-ASCII chars to make test independent of container settings. - private static final String NON_ASCII_STRING = "foob\u00E1r_\u263a"; // foobár_☺ + private static final String NON_ASCII_STRING = "foobár_☺"; private static final byte[] NON_ASCII_BYTES = NON_ASCII_STRING.getBytes(UTF_8); private static final int NON_ASCII_BUFFER_CAPACITY = NON_ASCII_BYTES.length + 1; diff --git a/components/environment/src/main/java/datadog/environment/OperatingSystem.java b/components/environment/src/main/java/datadog/environment/OperatingSystem.java index 1d24d7680c9..686bfca442d 100644 --- a/components/environment/src/main/java/datadog/environment/OperatingSystem.java +++ b/components/environment/src/main/java/datadog/environment/OperatingSystem.java @@ -1,5 +1,6 @@ package datadog.environment; +import static datadog.environment.OperatingSystem.Architecture.ARM64; import static datadog.environment.OperatingSystem.Type.LINUX; import static datadog.environment.OperatingSystem.Type.MACOS; import static datadog.environment.OperatingSystem.Type.WINDOWS; @@ -25,6 +26,15 @@ public final class OperatingSystem { private OperatingSystem() {} + /** + * Checks whether the architecture is arm64. + * + * @return @{@code true} if architecture is arm64, {@code false} otherwise. + */ + public static boolean isArm64() { + return ARCHITECTURE == ARM64; + } + /** * Checks whether the operating system is Linux based. * diff --git a/components/json/src/test/java/datadog/json/JsonReaderTest.java b/components/json/src/test/java/datadog/json/JsonReaderTest.java index 15a635c148a..e716a625103 100644 --- a/components/json/src/test/java/datadog/json/JsonReaderTest.java +++ b/components/json/src/test/java/datadog/json/JsonReaderTest.java @@ -215,8 +215,7 @@ void testStringEscaping() { assertEquals("\n", reader.nextString()); assertEquals("\r", reader.nextString()); assertEquals("\t", reader.nextString()); - // Explicit escape for non-ASCII `É` to make test independent of container settings. - assertEquals("\u00C9", reader.nextString()); + assertEquals("É", reader.nextString()); reader.endArray(); } catch (IOException e) { fail("Failed to read escaped JSON strings", e); diff --git a/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java index a0cf46ea89b..da13cbca0b5 100644 --- a/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java +++ b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java @@ -1,6 +1,5 @@ package datadog.crashtracking.buildid; -import static datadog.environment.OperatingSystem.Architecture.ARM64; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -138,7 +137,7 @@ private static Stream elfBinaries() { @MethodSource("elfBinaries") void testElfBuildIdExtraction(String containerPath, String description) throws Exception { // TODO: check if arm64 can be supported too. - assumeFalse(OperatingSystem.architecture() == ARM64, "Skipping for arm64"); + assumeFalse(OperatingSystem.isArm64(), "Skipping for arm64"); Path localBinary = copyFromContainer(linuxContainer, containerPath); ElfBuildIdExtractor extractor = new ElfBuildIdExtractor(); diff --git a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java index 62ca9ea29fe..62beaeba443 100644 --- a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java +++ b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java @@ -1,7 +1,5 @@ package com.datadog.profiling.controller; -import static datadog.environment.OperatingSystem.Architecture.ARM64; - import datadog.environment.JavaVirtualMachine; import datadog.environment.OperatingSystem; import datadog.environment.SystemProperties; @@ -243,11 +241,7 @@ private static boolean extractSoFromJar(Path target, StringBuilder sb) throws Ex .filter(e -> e.getName().contains("libjavaProfiler.so")) .filter( e -> - e.getName() - .contains( - OperatingSystem.architecture() == ARM64 - ? "/linux-arm64/" - : "/linux-x64/") + e.getName().contains(OperatingSystem.isArm64() ? "/linux-arm64/" : "/linux-x64/") && (!OperatingSystem.isMusl() || e.getName().contains("-musl"))) .findFirst() .map( diff --git a/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy b/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy index 57848379357..1c86d404784 100644 --- a/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy +++ b/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy @@ -1,6 +1,10 @@ package datadog.trace.instrumentation.aerospike4 +import static datadog.trace.agent.test.utils.PortUtils.waitForPortToOpen +import static java.util.concurrent.TimeUnit.SECONDS +import static org.testcontainers.containers.wait.strategy.Wait.forLogMessage +import com.github.dockerjava.api.model.Ulimit import datadog.trace.agent.test.asserts.TraceAssert import datadog.trace.agent.test.naming.VersionedNamingTestBase import datadog.trace.api.DDSpanTypes @@ -9,10 +13,6 @@ import datadog.trace.core.DDSpan import org.testcontainers.containers.GenericContainer import spock.lang.Shared -import static datadog.trace.agent.test.utils.PortUtils.waitForPortToOpen -import static java.util.concurrent.TimeUnit.SECONDS -import static org.testcontainers.containers.wait.strategy.Wait.forLogMessage - abstract class AerospikeBaseTest extends VersionedNamingTestBase { @Shared @@ -25,8 +25,14 @@ abstract class AerospikeBaseTest extends VersionedNamingTestBase { int aerospikePort = 3000 def setup() throws Exception { - aerospike = new GenericContainer('aerospike:5.5.0.9') + // arm64 supported since ce-6.2.0.2 + aerospike = new GenericContainer('aerospike:ce-6.2.0.2') .withExposedPorts(3000) + // proto-fd-max default is 15000, but container default is 1024. + // see: https://aerospike.com/docs/database/reference/config#service__proto-fd-max + .withCreateContainerCmdModifier({ cmd -> + cmd.getHostConfig().withUlimits([new Ulimit('nofile', 15000L, 15000L)] as Ulimit[]) + }) .waitingFor(forLogMessage(".*heartbeat-received.*\\n", 1)) aerospike.start() @@ -37,9 +43,7 @@ abstract class AerospikeBaseTest extends VersionedNamingTestBase { } def cleanup() throws Exception { - if (aerospike) { - aerospike.stop() - } + aerospike?.stop() } def aerospikeSpan(TraceAssert trace, int index, String methodName, Object parentSpan = null) { diff --git a/dd-java-agent/instrumentation/google-pubsub-1.116/src/test/groovy/PubSubTest.groovy b/dd-java-agent/instrumentation/google-pubsub-1.116/src/test/groovy/PubSubTest.groovy index 289822df042..07189f86b37 100644 --- a/dd-java-agent/instrumentation/google-pubsub-1.116/src/test/groovy/PubSubTest.groovy +++ b/dd-java-agent/instrumentation/google-pubsub-1.116/src/test/groovy/PubSubTest.groovy @@ -1,4 +1,3 @@ - import static datadog.trace.agent.test.utils.TraceUtils.basicSpan import com.google.api.gax.core.NoCredentialsProvider @@ -34,13 +33,12 @@ import datadog.trace.core.datastreams.StatsGroup import datadog.trace.instrumentation.grpc.client.GrpcClientDecorator import io.grpc.ManagedChannel import io.grpc.ManagedChannelBuilder +import java.nio.charset.StandardCharsets +import java.util.concurrent.CountDownLatch import org.testcontainers.containers.PubSubEmulatorContainer import org.testcontainers.utility.DockerImageName import spock.lang.Shared -import java.nio.charset.StandardCharsets -import java.util.concurrent.CountDownLatch - abstract class PubSubTest extends VersionedNamingTestBase { private static final String PROJECT_ID = "dd-trace-java" @@ -97,7 +95,7 @@ abstract class PubSubTest extends VersionedNamingTestBase { } def setupSpec() { - emulator = new PubSubEmulatorContainer(DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:495.0.0-emulators")) + emulator = new PubSubEmulatorContainer(DockerImageName.parse("gcr.io/google.com/cloudsdktool/google-cloud-cli:495.0.0-emulators")) emulator.start() channel = ManagedChannelBuilder.forTarget(emulator.getEmulatorEndpoint()).usePlaintext().build() transportChannelProvider = FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)) diff --git a/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy b/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy index 616b38a456d..4fb72863371 100644 --- a/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy @@ -2,11 +2,13 @@ import static datadog.trace.agent.test.utils.TraceUtils.basicSpan import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_TRACE_PREPARED_STATEMENTS +import static org.junit.jupiter.api.Assumptions.assumeTrue import com.mchange.v2.c3p0.ComboPooledDataSource import com.microsoft.sqlserver.jdbc.SQLServerException import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource +import datadog.environment.OperatingSystem import datadog.trace.agent.test.naming.VersionedNamingTestBase import datadog.trace.agent.test.utils.PortUtils import datadog.trace.api.Config @@ -90,6 +92,10 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { @Shared private Map> cpDatasources = new HashMap<>() + private static boolean dockerImageSupported(String db) { + return !(db == SQLSERVER && OperatingSystem.isArm64() && OperatingSystem.isLinux()) + } + def peerConnectionProps(String db){ def props = new Properties() props.setProperty("user", jdbcUserNames.get(db)) @@ -158,6 +164,11 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { def createDS(String connectionPoolName, String dbType, String jdbcUrl) { DataSource ds = null + + if (!dockerImageSupported(dbType)) { + return ds + } + if (connectionPoolName == "tomcat") { ds = createTomcatDS(dbType, jdbcUrl) } @@ -196,10 +207,12 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { jdbcUrls.put(MYSQL, "${mysql.getJdbcUrl()}") // SQLSERVER - sqlserver = new MSSQLServerContainer(MSSQLServerContainer.IMAGE).acceptLicense().withPassword(jdbcPasswords.get(SQLSERVER)) - sqlserver.start() - PortUtils.waitForPortToOpen(sqlserver.getHost(), sqlserver.getMappedPort(MSSQLServerContainer.MS_SQL_SERVER_PORT), 5, TimeUnit.SECONDS) - jdbcUrls.put(SQLSERVER, "${sqlserver.getJdbcUrl()};DatabaseName=${dbName.get(SQLSERVER)}") + if (dockerImageSupported(SQLSERVER)) { + sqlserver = new MSSQLServerContainer(MSSQLServerContainer.IMAGE).acceptLicense().withPassword(jdbcPasswords.get(SQLSERVER)) + sqlserver.start() + PortUtils.waitForPortToOpen(sqlserver.getHost(), sqlserver.getMappedPort(MSSQLServerContainer.MS_SQL_SERVER_PORT), 5, TimeUnit.SECONDS) + jdbcUrls.put(SQLSERVER, "${sqlserver.getJdbcUrl()};DatabaseName=${dbName.get(SQLSERVER)}") + } // ORACLE // Earlier Oracle version images (oracle-xe) don't work on arm64 @@ -1026,6 +1039,8 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { } Connection setupConnection(String pool, String db) { + assumeTrue(dockerImageSupported(db)) + def conn = pool ? cpDatasources.get(pool).get(db).getConnection() : connectTo(db, peerConnectionProps(db)) // Clear any traces that pool or db can emmit on connection creation. diff --git a/dd-java-agent/instrumentation/protobuf-3.0/build.gradle b/dd-java-agent/instrumentation/protobuf-3.0/build.gradle index e262abdd272..173eaf3f490 100644 --- a/dd-java-agent/instrumentation/protobuf-3.0/build.gradle +++ b/dd-java-agent/instrumentation/protobuf-3.0/build.gradle @@ -1,3 +1,5 @@ +import datadog.gradle.plugin.HostPlatform + plugins { id 'com.google.protobuf' version '0.9.4' } @@ -14,13 +16,11 @@ muzzle { } } + protobuf { protoc { - def os = System.getProperty("os.name").toLowerCase() - def arch = System.getProperty("os.arch").toLowerCase() - - // There is no m1 support for protoc 3.0.0, so require Rosetta - if (os.contains("mac") && arch.contains("aarch64")) { + // There is no macOS arm64 support for protoc 3.0.0, so require Rosetta. + if (HostPlatform.isMacArm64()) { artifact = "com.google.protobuf:protoc:3.0.0:osx-x86_64" } else { artifact = "com.google.protobuf:protoc:3.0.0" @@ -28,6 +28,23 @@ protobuf { } } +// protobuf supports arm64 linux since 3.12.0, but it is not source-compatible with 3.0.0 +if (HostPlatform.isLinuxArm64()) { + tasks.matching { + it.name in [ + "extractTestProto", + "generateTestProto", + "compileTestJava", + "compileTestGroovy", + "processTestResources", + "testClasses", + "test" + ] + }.configureEach { + enabled = false + } +} + dependencies { compileOnly group: 'com.google.protobuf', name: 'protobuf-java', version: '3.0.0' diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy index 25aba9b9660..0d740d17e41 100644 --- a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy @@ -252,6 +252,13 @@ abstract class AbstractSmokeTest extends ProcessManager { // Unlike crash tracking smoke test, keep the default delay; otherwise, otherwise other tests will fail // ret += "-Ddd.dogstatsd.start-delay=0" } + + // Disable CDS on Linux arm64: Temurin 11.0.31 / 21.0.10 hit a SIGSEGV during + // shared-class restore (ClassLoaderData::add_handle, Klass::class_loader) + // before any user code runs. + if (OperatingSystem.isArm64() && OperatingSystem.isLinux()) { + ret += "-Xshare:off" + } ret as String[] } diff --git a/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy b/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy index 28b72c111c7..471716b203d 100644 --- a/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy +++ b/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy @@ -1,6 +1,7 @@ package datadog.smoketest +import datadog.environment.OperatingSystem import java.time.Duration import java.util.concurrent.ArrayBlockingQueue import java.util.concurrent.BlockingQueue @@ -11,6 +12,7 @@ import org.testcontainers.containers.GenericContainer import org.testcontainers.containers.output.Slf4jLogConsumer import org.testcontainers.containers.wait.strategy.Wait import org.testcontainers.utility.MountableFile +import spock.lang.IgnoreIf import spock.lang.Shared /** @@ -22,6 +24,11 @@ import spock.lang.Shared * * Note that the websphere related metrics will only arrive if our instrumentation is applied. */ +// IBM does not publish an arm64 build of icr.io/appcafe/websphere-traditional, and the +// arm64 CI runner has no amd64 emulation configured, so the container fails to start. +@IgnoreIf({ + OperatingSystem.isArm64() && OperatingSystem.isLinux() +}) class WebSphereJmxSmokeTest extends AbstractSmokeTest { private static final Logger LOG = LoggerFactory.getLogger(WebSphereJmxSmokeTest) From 2901752e24add2d0206a7b6892535cdb0f1e034f Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 14:39:25 -0400 Subject: [PATCH 02/24] Fixed netty on arm64 --- .../java-concurrent-1.8/build.gradle | 8 ++++++++ .../NettyExecutorInstrumentationTest.groovy | 14 ++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle index ee85bef77fa..5097bfb89ab 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle @@ -1,3 +1,5 @@ +import datadog.gradle.plugin.HostPlatform + muzzle { pass { coreJdk() @@ -17,6 +19,12 @@ dependencies { testImplementation libs.guava testImplementation group: 'io.netty', name: 'netty-all', version: '4.1.9.Final' testImplementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '7.0.0' + + if (HostPlatform.isLinuxArm64()) { + // netty-all 4.1.9 only ships the linux-x86_64 epoll native; pull the aarch64 one explicitly. + testImplementation group: 'io.netty', name: 'netty-transport-native-epoll', version: '4.1.108.Final', classifier: 'linux-aarch_64' + } + // Tomcat 10.1.+ seems to require Java 11. Limit to fix build. // TODO: Tomcat 10.0.10 has a copy of the JSR166 ThreadPoolExecutor so it needs special instrumentation latestDepTestImplementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '10.0.8' diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy index fc944416d94..d06fcdc6487 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy @@ -1,5 +1,8 @@ package executor +import static org.junit.jupiter.api.Assumptions.assumeTrue + +import datadog.environment.OperatingSystem import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.api.Trace import datadog.trace.core.DDSpan @@ -8,22 +11,17 @@ import io.netty.channel.epoll.EpollEventLoopGroup import io.netty.channel.local.LocalEventLoopGroup import io.netty.channel.nio.NioEventLoopGroup import io.netty.util.concurrent.DefaultEventExecutorGroup -import runnable.JavaAsyncChild -import spock.lang.Shared - import java.lang.reflect.InvocationTargetException import java.util.concurrent.Callable import java.util.concurrent.Future import java.util.concurrent.RejectedExecutionException import java.util.concurrent.TimeUnit - -import static org.junit.jupiter.api.Assumptions.assumeTrue +import runnable.JavaAsyncChild +import spock.lang.Shared class NettyExecutorInstrumentationTest extends InstrumentationSpecification { - @Shared - boolean isLinux = System.getProperty("os.name").toLowerCase().contains("linux") - + boolean isLinux = OperatingSystem.isLinux() @Shared EpollEventLoopGroup epollEventLoopGroup = isLinux ? new EpollEventLoopGroup(4) : null @Shared From 3506190b6c82e23034d83e1d761c3b9891742869 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 15:05:46 -0400 Subject: [PATCH 03/24] Fixed Java crashes on arm64 Linux during CDS --- .../plugin/instrument/InstrumentPostProcessingAction.kt | 5 +++++ .../kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt index b8c3e300afd..3f70bac7dec 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt @@ -1,5 +1,6 @@ package datadog.gradle.plugin.instrument +import datadog.gradle.plugin.HostPlatform import datadog.gradle.plugin.instrument.BuildTimeInstrumentationPlugin.Companion.BUILD_TIME_INSTRUMENTATION_PLUGIN_CONFIGURATION import org.gradle.api.Action import org.gradle.api.Project @@ -73,6 +74,10 @@ abstract class InstrumentPostProcessingAction @Inject constructor( return workerExecutor.processIsolation { forkOptions { setExecutable(javaLauncher.executablePath.asFile.absolutePath) + if (HostPlatform.isLinuxArm64()) { + // Temurin on the arm64 Linux can crash during CDS shared-class restore; + jvmArgs("-Xshare:off") + } } } } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt index 2d5d830ea3b..08d42673298 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt @@ -1,5 +1,6 @@ package datadog.gradle.plugin.muzzle.tasks +import datadog.gradle.plugin.HostPlatform import datadog.gradle.plugin.muzzle.MuzzleAction import datadog.gradle.plugin.muzzle.MuzzleDirective import datadog.gradle.plugin.muzzle.MuzzleExtension @@ -102,6 +103,10 @@ abstract class MuzzleTask @Inject constructor( if(javaLauncher.metadata.languageVersion > JavaLanguageVersion.of(9)) { jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") } + if (HostPlatform.isLinuxArm64()) { + // Temurin on the arm64 Linux can crash during CDS shared-class restore; + jvmArgs("-Xshare:off") + } executable(javaLauncher.executablePath) } } From bf4f3fb3ee2b053866b8d4d442edf61381f2aadc Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 15:11:41 -0400 Subject: [PATCH 04/24] Fixed RestletTest on arm64 Linux --- .../src/latestDepTest/groovy/RestletTest.groovy | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy b/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy index 3217e53394d..2c308efeb29 100644 --- a/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy +++ b/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy @@ -1,3 +1,6 @@ +import static datadog.environment.OperatingSystem.isArm64 +import static datadog.environment.OperatingSystem.isLinux + import org.restlet.Request import org.restlet.Response import org.restlet.data.Header @@ -6,6 +9,12 @@ import org.restlet.util.Series class RestletTest extends RestletTestBase { + @Override + boolean testParallelRequest() { + // TODO: Parallel processing is failing on Linux arm64. + return !(isLinux() && isArm64()) + } + @Override protected Filter createHeaderFilter() { return new ResponseHeaderFilter() From 75eaaf7579fbdf43672645706674bafeeb4713e5 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 15:23:48 -0400 Subject: [PATCH 05/24] Fixed debugger on Linux arm64 --- .../smoketest/ProcessBuilderHelper.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java index 5faf29bbaa5..7947a8badf8 100644 --- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java +++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java @@ -1,5 +1,6 @@ package datadog.smoketest; +import datadog.environment.OperatingSystem; import java.io.File; import java.nio.file.Path; import java.util.ArrayList; @@ -43,16 +44,22 @@ public static ProcessBuilder createProcessBuilder( + System.nanoTime(); List baseCommand = - Arrays.asList( - javaPath(), - // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:5006", - "-Xmx" + System.getProperty("datadog.forkedMaxHeapSize", "1024M"), - "-Xms" + System.getProperty("datadog.forkedMinHeapSize", "64M"), - "-javaagent:" + agentShadowJar(), - "-XX:ErrorFile=/tmp/hs_err_pid%p.log", - "-Ddd.env=smoketest", - "-Ddd.version=99", - "-Djava.util.prefs.userRoot=" + prefsDir); + new ArrayList<>( + Arrays.asList( + javaPath(), + // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:5006", + "-Xmx" + System.getProperty("datadog.forkedMaxHeapSize", "1024M"), + "-Xms" + System.getProperty("datadog.forkedMinHeapSize", "64M"), + "-javaagent:" + agentShadowJar(), + "-XX:ErrorFile=/tmp/hs_err_pid%p.log", + "-Ddd.env=smoketest", + "-Ddd.version=99", + "-Djava.util.prefs.userRoot=" + prefsDir)); + + if (OperatingSystem.isLinux() && OperatingSystem.isArm64()) { + // Temurin on the arm64 Linux can crash during CDS shared-class restore; + baseCommand.add(1, "-Xshare:off"); + } List command = new ArrayList<>(); command.addAll(baseCommand); From 50c71e5a1a561209ad1247b689350b8013fa88e2 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 15:41:15 -0400 Subject: [PATCH 06/24] Fixed ByteBuddy issue on arm64: `Could not self-attach to current VM`. --- .../dd-trace-java.test-jvm-constraints.gradle.kts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts index aa4724183b0..dfe3cfa52c2 100644 --- a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts +++ b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts @@ -1,3 +1,4 @@ +import datadog.gradle.plugin.HostPlatform import datadog.gradle.plugin.testJvmConstraints.ProvideJvmArgsOnJvmLauncherVersion import datadog.gradle.plugin.testJvmConstraints.TestJvmConstraintsExtension import datadog.gradle.plugin.testJvmConstraints.TestJvmConstraintsExtension.Companion.TEST_JVM_CONSTRAINTS @@ -79,6 +80,16 @@ private fun Test.configureTestJvm(extension: TestJvmConstraintsExtension) { ), extension.allowReflectiveAccessToJdk ) + + // Fix for arm64 Linux ByteBuddy error: + // "Could not self-attach to current VM using external process" + // Why it is needed on arm64: probably arm64 GitLab runners has stricter rules applied. + if (HostPlatform.isLinuxArm64()) { + conditionalJvmArgs( + JavaVersion.VERSION_1_9, + listOf("-Djdk.attach.allowAttachSelf=true") + ) + } } // Jacoco plugin is not applied on every project From 71c1bb05ab5a6959758a1381391b9e13f3b1db13 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 15:42:18 -0400 Subject: [PATCH 07/24] Optimize K8s resources. --- .gitlab-ci.yml | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index df5e8f5014a..147d26c3772 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -168,6 +168,24 @@ default: echo -e "${TEXT_BOLD}${TEXT_YELLOW} Containers:${TEXT_CLEAR} https://app.datadoghq.com/containers?${TIME_PARAMS}query=image_name%3A%2A%2Fdatadog%2Fdd-trace-java-docker-build%20AND%20pod_name%3A${POD_NAME}&live=false" echo -e "${TEXT_BOLD}${TEXT_YELLOW} Processes:${TEXT_CLEAR} https://app.datadoghq.com/process?${TIME_PARAMS}query=image_name%3A%2A%2Fdatadog%2Fdd-trace-java-docker-build%20AND%20pod_name%3A${POD_NAME}&live=false" +.tier_m: + variables: &tier_m_variables + GRADLE_WORKERS: 4 + GRADLE_MEMORY_MIN: 1G + GRADLE_MEMORY_MAX: 5G + KUBERNETES_CPU_REQUEST: 6 + KUBERNETES_MEMORY_REQUEST: 16Gi + KUBERNETES_MEMORY_LIMIT: 16Gi + +.tier_l: + variables: &tier_l_variables + GRADLE_WORKERS: 6 + GRADLE_MEMORY_MIN: 1G + GRADLE_MEMORY_MAX: 6G + KUBERNETES_CPU_REQUEST: 10 + KUBERNETES_MEMORY_REQUEST: 20Gi + KUBERNETES_MEMORY_LIMIT: 20Gi + .gitlab_base_ref_params: &gitlab_base_ref_params - | export GIT_BASE_REF=$(.gitlab/find-gh-base-ref.sh) @@ -692,18 +710,10 @@ muzzle-dep-report: stage: tests-arm64 needs: [] variables: + <<: *tier_m_variables # arm64 docker image installs only these JVMs; override the global default regex. DEFAULT_TEST_JVMS: /^(8|11|17|21|25)$/ GRADLE_PARAMS: "-PskipFlakyTests" - GRADLE_WORKERS: 6 - GRADLE_MEMORY_MIN: 1G - GRADLE_MEMORY_MAX: 4G - # Sized for the arm64 microvm runner pool (smaller than amd64). - # Observed peak on equivalent amd64 workload: ~14.5 GB / ~1.5 vCPU avg. - # Bump back up if jobs OOM or we see CPU throttling in cgroup-info. - KUBERNETES_CPU_REQUEST: 6 - KUBERNETES_MEMORY_REQUEST: 12Gi - KUBERNETES_MEMORY_LIMIT: 16Gi TESTCONTAINERS_CHECKS_DISABLE: "true" TESTCONTAINERS_RYUK_DISABLED: "true" TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX: "registry.ddbuild.io/images/mirror/" @@ -869,6 +879,7 @@ test_inst: test_inst_arm64: extends: .test_job_arm64_with_test_agent variables: + <<: *tier_l_variables GRADLE_TARGET: ":instrumentationTest" CACHE_TYPE: "inst" parallel: @@ -889,6 +900,7 @@ test_inst_latest: test_inst_latest_arm64: extends: .test_job_arm64_with_test_agent variables: + <<: *tier_l_variables GRADLE_TARGET: ":instrumentationLatestDepTest" CACHE_TYPE: "latestdep" parallel: @@ -977,6 +989,7 @@ test_smoke: test_smoke_arm64: extends: .test_job_arm64 variables: + <<: *tier_l_variables GRADLE_TARGET: "stageMainDist :smokeTest" GRADLE_PARAMS: "-PskipFlakyTests" CACHE_TYPE: "smoke" @@ -1003,6 +1016,7 @@ test_ssi_smoke: test_ssi_smoke_arm64: extends: .test_job_arm64 variables: + <<: *tier_l_variables GRADLE_TARGET: "stageMainDist :smokeTest" CACHE_TYPE: "smoke" DD_INJECT_FORCE: "true" @@ -1025,6 +1039,7 @@ test_smoke_graalvm: test_smoke_graalvm_arm64: extends: .test_job_arm64 variables: + <<: *tier_l_variables GRADLE_TARGET: "stageMainDist :dd-smoke-test:spring-boot-3.0-native:test" CACHE_TYPE: "smoke" CI_NO_SPLIT: "true" From 79715861961950aafdcdd8581f2a64f3c2860220 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 18:44:14 -0400 Subject: [PATCH 08/24] Fixed netty on arm64 --- .../java-concurrent-1.8/build.gradle | 11 ++----- .../java-concurrent-1.8/gradle.lockfile | 32 ++++++++++++++++++- .../RunnableFutureInstrumentation.java | 9 ++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle index 5097bfb89ab..98ba8af8c3a 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle @@ -1,5 +1,3 @@ -import datadog.gradle.plugin.HostPlatform - muzzle { pass { coreJdk() @@ -17,16 +15,11 @@ addTestSuiteForDir('latestDepTest', 'test') dependencies { testImplementation project(':dd-java-agent:instrumentation:datadog:tracing:trace-annotation') testImplementation libs.guava - testImplementation group: 'io.netty', name: 'netty-all', version: '4.1.9.Final' + // netty-all ships with the linux arm64 libs only since 4.1.50+ + testImplementation group: 'io.netty', name: 'netty-all', version: '4.1.50.Final' testImplementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '7.0.0' - if (HostPlatform.isLinuxArm64()) { - // netty-all 4.1.9 only ships the linux-x86_64 epoll native; pull the aarch64 one explicitly. - testImplementation group: 'io.netty', name: 'netty-transport-native-epoll', version: '4.1.108.Final', classifier: 'linux-aarch_64' - } - // Tomcat 10.1.+ seems to require Java 11. Limit to fix build. // TODO: Tomcat 10.0.10 has a copy of the JSR166 ThreadPoolExecutor so it needs special instrumentation latestDepTestImplementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '10.0.8' } - diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile index e918d10d18f..fc190d59b60 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile @@ -47,7 +47,37 @@ commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeC commons-io:commons-io:2.20.0=spotbugs de.thetaphi:forbiddenapis:3.10=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath io.leangen.geantyref:geantyref:1.3.16=latestDepTestRuntimeClasspath,testRuntimeClasspath -io.netty:netty-all:4.1.9.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-all:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-buffer:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-dns:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-haproxy:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-http2:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-http:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-memcache:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-mqtt:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-redis:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-smtp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-socks:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-stomp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-xml:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-common:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-handler-proxy:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-handler-ssl-ocsp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-handler:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-resolver-dns-classes-macos:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-resolver-dns-native-macos:4.1.133.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.netty:netty-resolver-dns:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-resolver:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport-classes-epoll:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport-classes-kqueue:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport-native-epoll:4.1.133.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.netty:netty-transport-native-kqueue:4.1.133.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.netty:netty-transport-native-unix-common:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport-rxtx:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport-sctp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport-udt:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath io.sqreen:libsqreen:17.3.0=latestDepTestRuntimeClasspath,testRuntimeClasspath javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath jaxen:jaxen:2.0.0=spotbugs diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java index a783258c421..e069b09341d 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java @@ -30,7 +30,9 @@ import java.util.Collection; import java.util.Map; import java.util.concurrent.Callable; +import java.util.concurrent.Delayed; import java.util.concurrent.RunnableFuture; +import java.util.concurrent.TimeUnit; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -147,6 +149,13 @@ public static void captureScope(@Advice.This RunnableFuture task) { public static final class Run { @Advice.OnMethodEnter public static AgentScope activate(@Advice.This RunnableFuture task) { + // Newer Netty versions may execute a delayed ScheduledFutureTask once only to move it into + // the scheduled queue. Keep the continuation for the run that actually invokes the task. + if (task instanceof Delayed + && task.getClass().getName().endsWith(".netty.util.concurrent.ScheduledFutureTask") + && ((Delayed) task).getDelay(TimeUnit.NANOSECONDS) > 0) { + return null; + } return startTaskScope(InstrumentationContext.get(RunnableFuture.class, State.class), task); } From 0384ca29af6ef289cbe88966de21c09773f17607 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 18:57:29 -0400 Subject: [PATCH 09/24] Fix for play gradle plugin on arm64 --- dd-smoke-tests/play-2.4/build.gradle | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/dd-smoke-tests/play-2.4/build.gradle b/dd-smoke-tests/play-2.4/build.gradle index 1a0de08b58b..4645fd91e74 100644 --- a/dd-smoke-tests/play-2.4/build.gradle +++ b/dd-smoke-tests/play-2.4/build.gradle @@ -1,3 +1,9 @@ +import datadog.gradle.plugin.HostPlatform +import org.gradle.playframework.tasks.RoutesCompile +import org.gradle.playframework.tasks.internal.RoutesCompileWorkAction +import org.gradle.playframework.tools.internal.routes.DefaultRoutesCompileSpec +import org.gradle.playframework.tools.internal.routes.RoutesCompilerFactory + plugins { id 'org.gradle.playframework' } @@ -93,6 +99,40 @@ tasks.withType(AbstractCopyTask).configureEach { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } +if (HostPlatform.isLinuxArm64()) { + tasks.named("compilePlayRoutes", RoutesCompile) { RoutesCompile task -> + // org.gradle.playframework.tasks.RoutesCompile does not expose worker fork options, but its + // worker JVM needs CDS disabled on Linux arm64 like the other forked JVMs in this build. + def workerExecutorField = RoutesCompile.getDeclaredField("workerExecutor") + workerExecutorField.accessible = true + + task.actions.clear() + task.doLast { + def spec = new DefaultRoutesCompileSpec( + task.source.files, + task.outputDirectory.get().asFile, + task.javaProject, + task.namespaceReverseRouter.get(), + task.generateReverseRoutes.get(), + task.injectedRoutesGenerator.get(), + task.additionalImports.get(), + projectDir + ) + + def workerExecutor = workerExecutorField.get(task) + workerExecutor.processIsolation { workerSpec -> + workerSpec.forkOptions { options -> + options.jvmArgs("-XX:MaxMetaspaceSize=256m", "-Xshare:off") + } + workerSpec.classpath.from(task.routesCompilerClasspath) + }.submit(RoutesCompileWorkAction) { parameters -> + parameters.compiler.set(RoutesCompilerFactory.create(task.platform.get())) + parameters.spec.set(spec) + } + } + } +} + spotless { java { target "**/*.java" From 5dca385ab7ec54b6a157cfb0e771d4eb782ecdd1 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 8 May 2026 21:35:22 -0400 Subject: [PATCH 10/24] Revert changes and simply skip netty test on arm64 linux. --- .../java-concurrent-1.8/build.gradle | 4 +-- .../java-concurrent-1.8/gradle.lockfile | 32 +------------------ .../RunnableFutureInstrumentation.java | 9 ------ .../NettyExecutorInstrumentationTest.groovy | 7 ++++ 4 files changed, 9 insertions(+), 43 deletions(-) diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle index 98ba8af8c3a..83caaeb1324 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/build.gradle @@ -15,10 +15,8 @@ addTestSuiteForDir('latestDepTest', 'test') dependencies { testImplementation project(':dd-java-agent:instrumentation:datadog:tracing:trace-annotation') testImplementation libs.guava - // netty-all ships with the linux arm64 libs only since 4.1.50+ - testImplementation group: 'io.netty', name: 'netty-all', version: '4.1.50.Final' + testImplementation group: 'io.netty', name: 'netty-all', version: '4.1.9.Final' testImplementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '7.0.0' - // Tomcat 10.1.+ seems to require Java 11. Limit to fix build. // TODO: Tomcat 10.0.10 has a copy of the JSR166 ThreadPoolExecutor so it needs special instrumentation latestDepTestImplementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '10.0.8' diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile index fc190d59b60..e918d10d18f 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/gradle.lockfile @@ -47,37 +47,7 @@ commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeC commons-io:commons-io:2.20.0=spotbugs de.thetaphi:forbiddenapis:3.10=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath io.leangen.geantyref:geantyref:1.3.16=latestDepTestRuntimeClasspath,testRuntimeClasspath -io.netty:netty-all:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-buffer:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-dns:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-haproxy:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-http2:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-http:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-memcache:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-mqtt:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-redis:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-smtp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-socks:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-stomp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec-xml:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-common:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-handler-proxy:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-handler-ssl-ocsp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-handler:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-resolver-dns-classes-macos:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-resolver-dns-native-macos:4.1.133.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath -io.netty:netty-resolver-dns:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-resolver:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-classes-epoll:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-classes-kqueue:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-native-epoll:4.1.133.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath -io.netty:netty-transport-native-kqueue:4.1.133.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath -io.netty:netty-transport-native-unix-common:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-rxtx:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-sctp:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-udt:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport:4.1.133.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-all:4.1.9.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath io.sqreen:libsqreen:17.3.0=latestDepTestRuntimeClasspath,testRuntimeClasspath javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath jaxen:jaxen:2.0.0=spotbugs diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java index e069b09341d..a783258c421 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/runnable/RunnableFutureInstrumentation.java @@ -30,9 +30,7 @@ import java.util.Collection; import java.util.Map; import java.util.concurrent.Callable; -import java.util.concurrent.Delayed; import java.util.concurrent.RunnableFuture; -import java.util.concurrent.TimeUnit; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -149,13 +147,6 @@ public static void captureScope(@Advice.This RunnableFuture task) { public static final class Run { @Advice.OnMethodEnter public static AgentScope activate(@Advice.This RunnableFuture task) { - // Newer Netty versions may execute a delayed ScheduledFutureTask once only to move it into - // the scheduled queue. Keep the continuation for the run that actually invokes the task. - if (task instanceof Delayed - && task.getClass().getName().endsWith(".netty.util.concurrent.ScheduledFutureTask") - && ((Delayed) task).getDelay(TimeUnit.NANOSECONDS) > 0) { - return null; - } return startTaskScope(InstrumentationContext.get(RunnableFuture.class, State.class), task); } diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy index d06fcdc6487..48b8267c5b8 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy @@ -17,11 +17,18 @@ import java.util.concurrent.Future import java.util.concurrent.RejectedExecutionException import java.util.concurrent.TimeUnit import runnable.JavaAsyncChild +import spock.lang.IgnoreIf import spock.lang.Shared +// TODO: netty-all 4.1.9 only ships linux-x86_64 epoll native libraries. +@IgnoreIf({ + OperatingSystem.isLinux() && OperatingSystem.isArm64() +}) class NettyExecutorInstrumentationTest extends InstrumentationSpecification { + @Shared boolean isLinux = OperatingSystem.isLinux() + @Shared EpollEventLoopGroup epollEventLoopGroup = isLinux ? new EpollEventLoopGroup(4) : null @Shared From 8865f78c4e6983085a22be70a1f0a2bae0765eb7 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 20 May 2026 13:59:27 -0400 Subject: [PATCH 11/24] Changes to test on multi-arch docker image. --- .gitlab-ci.yml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5c05e7fe9f5..692ea8acf67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,10 +53,8 @@ variables: GRADLE_VERSION: "8.14.4" # must match gradle-wrapper.properties MAVEN_REPOSITORY_PROXY: "https://depot-read-api-java.us1.ddbuild.io/magicmirror/magicmirror/@current/" GRADLE_PLUGIN_PROXY: "https://depot-read-api-java.us1.ddbuild.io/magicmirror/magicmirror/@current/" - ARM64_BUILDER_IMAGE_REPO: "registry.ddbuild.io/images/mirror/dd-trace-java-docker-build" - ARM64_BUILDER_IMAGE_TAG: "alexeyk_arm64-test-arm64-base" BUILDER_IMAGE_REPO: "registry.ddbuild.io/images/mirror/dd-trace-java-docker-build" # images are pinned in images/mirror.lock.yaml in the DataDog/images repo - BUILDER_IMAGE_VERSION_PREFIX: "ci-" # use either an empty string (e.g. "") for latest images or a version followed by a hyphen (e.g. "ci-" or "123_merge-") + BUILDER_IMAGE_VERSION_PREFIX: "163_merge-" # use either an empty string (e.g. "") for latest images or a version followed by a hyphen (e.g. "ci-" or "123_merge-") REPO_NOTIFICATION_CHANNEL: "#apm-java-escalations" DEFAULT_TEST_JVMS: /^(8|11|17|21|25|tip)$/ # the latest "tip" version is 26 PROFILE_TESTS: @@ -197,13 +195,8 @@ default: image: ${BUILDER_IMAGE_REPO}:${BUILDER_IMAGE_VERSION_PREFIX}base stage: build variables: + <<: *tier_m_variables MAVEN_OPTS: "-Xms256M -Xmx1024M" - GRADLE_WORKERS: 6 - GRADLE_MEMORY_MIN: 1G - GRADLE_MEMORY_MAX: 4G - KUBERNETES_CPU_REQUEST: 10 - KUBERNETES_MEMORY_REQUEST: 20Gi - KUBERNETES_MEMORY_LIMIT: 20Gi CACHE_TYPE: "lib" #default FF_USE_FASTZIP: "true" CACHE_COMPRESSION_LEVEL: "slowest" @@ -635,6 +628,7 @@ muzzle-dep-report: needs: [ build_tests ] stage: tests variables: + <<: *tier_m_variables GRADLE_PARAMS: "-PskipFlakyTests" CONTINUE_ON_FAILURE: "false" TESTCONTAINERS_CHECKS_DISABLE: "true" @@ -703,14 +697,14 @@ muzzle-dep-report: - data_integrity_failure .test_job_arm64: - image: ${ARM64_BUILDER_IMAGE_REPO}:${ARM64_BUILDER_IMAGE_TAG} + image: ${BUILDER_IMAGE_REPO}:${BUILDER_IMAGE_VERSION_PREFIX}base tags: [ "docker-in-docker:arm64" ] stage: tests-arm64 needs: [] variables: <<: *tier_m_variables - # arm64 docker image installs only these JVMs; override the global default regex. - DEFAULT_TEST_JVMS: /^(8|11|17|21|25)$/ + # arm64 does not include JDK 7 or ibm8 (upstream images not published for arm64). + DEFAULT_TEST_JVMS: /^(8|11|17|21|25|tip)$/ GRADLE_PARAMS: "-PskipFlakyTests" TESTCONTAINERS_CHECKS_DISABLE: "true" TESTCONTAINERS_RYUK_DISABLED: "true" @@ -869,6 +863,7 @@ test_base_arm64: test_inst: extends: .test_job_with_test_agent variables: + <<: *tier_l_variables GRADLE_TARGET: ":instrumentationTest" CACHE_TYPE: "inst" parallel: @@ -886,6 +881,7 @@ test_inst_arm64: test_inst_latest: extends: .test_job_with_test_agent variables: + <<: *tier_l_variables GRADLE_TARGET: ":instrumentationLatestDepTest" CACHE_TYPE: "latestdep" parallel: @@ -978,6 +974,7 @@ test_debugger_arm64: test_smoke: extends: .test_job variables: + <<: *tier_l_variables GRADLE_TARGET: "stageMainDist :smokeTest" GRADLE_PARAMS: "-PskipFlakyTests" CACHE_TYPE: "smoke" @@ -1004,6 +1001,7 @@ test_ssi_smoke: - if: '$CI_COMMIT_BRANCH =~ /^gh-readonly-queue/' when: on_success variables: + <<: *tier_l_variables GRADLE_TARGET: "stageMainDist :smokeTest" CACHE_TYPE: "smoke" DD_INJECT_FORCE: "true" @@ -1026,6 +1024,7 @@ test_smoke_graalvm: extends: .test_job tags: [ "arch:amd64" ] variables: + <<: *tier_l_variables GRADLE_TARGET: "stageMainDist :dd-smoke-test:spring-boot-3.0-native:test" CACHE_TYPE: "smoke" CI_NO_SPLIT: "true" @@ -1036,14 +1035,16 @@ test_smoke_graalvm: test_smoke_graalvm_arm64: extends: .test_job_arm64 + image: ${BUILDER_IMAGE_REPO}:${BUILDER_IMAGE_VERSION_PREFIX}$testJvm variables: <<: *tier_l_variables GRADLE_TARGET: "stageMainDist :dd-smoke-test:spring-boot-3.0-native:test" CACHE_TYPE: "smoke" CI_NO_SPLIT: "true" + NON_DEFAULT_JVMS: "true" parallel: matrix: - - testJvm: ["graalvm21"] + - testJvm: ["graalvm17", "graalvm21", "graalvm25"] test_smoke_semeru8_debugger: extends: .test_job From 0cfbcc8c053f894393e10a30de95caa70231ac10 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 20 May 2026 14:36:46 -0400 Subject: [PATCH 12/24] Fixed rule for GraalVM. --- .gitlab-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 692ea8acf67..d13e4e20325 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -716,6 +716,9 @@ muzzle-dep-report: - if: $testJvm =~ $DEFAULT_TEST_JVMS when: manual allow_failure: true + - if: '$NON_DEFAULT_JVMS == "true"' + when: manual + allow_failure: true cache: - key: dependency-$CACHE_TYPE paths: From 978c998dfde63329bb84e7feb238a20894300406 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Thu, 21 May 2026 16:30:04 -0400 Subject: [PATCH 13/24] Minor polishing. --- .gitlab-ci.yml | 5 +- build.gradle.kts | 6 +- .../InstrumentPostProcessingAction.kt | 2 +- .../gradle/plugin/muzzle/tasks/MuzzleTask.kt | 2 +- ...trace-java.test-jvm-constraints.gradle.kts | 3 +- .../aerospike4/AerospikeBaseTest.groovy | 2 +- .../RemoteJDBCInstrumentationTest.groovy | 509 ++++++++++-------- .../instrumentation/protobuf-3.0/build.gradle | 2 +- .../smoketest/ProcessBuilderHelper.java | 2 +- dd-smoke-tests/play-2.4/build.gradle | 4 +- .../smoketest/AbstractSmokeTest.groovy | 4 +- .../smoketest/WebSphereJmxSmokeTest.groovy | 3 +- 12 files changed, 293 insertions(+), 251 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d13e4e20325..9d963289833 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -755,12 +755,9 @@ muzzle-dep-report: - sed -i "s|https://repo.maven.apache.org/maven2/|$MAVEN_REPOSITORY_PROXY|g" .mvn/wrapper/maven-wrapper.properties - *normalize_node_index - *prepare_test_env + # Disable CDS in forked JVMs to avoid SIGSEGVs on Linux arm64. - export GRADLE_OPTS="-Dorg.gradle.jvmargs='-Xshare:off -Xms$GRADLE_MEMORY_MIN -Xmx$GRADLE_MEMORY_MAX -XX:ErrorFile=/tmp/hs_err_pid%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Djava.util.prefs.userRoot=/tmp/.java/.userPrefs-${CI_JOB_ID}' -Ddatadog.forkedMinHeapSize=128M -Ddatadog.forkedMaxHeapSize=1024M" - export GRADLE_ARGS="--build-cache --stacktrace --no-daemon --parallel --max-workers=$GRADLE_WORKERS" - # Disable CDS (Class Data Sharing) for the Gradle daemon. - # Temurin 11 on the arm64 microvm runner SIGSEGVs in ClassLoaderData::add_handle - # while restoring archived class mirrors from classes.jsa during JVM startup; - # -Xshare:off bypasses the crashing path. - ./gradlew --version script: - ./gradlew $GRADLE_TARGET $GRADLE_PARAMS -PtestJvm=$testJvm -Pslot=$CI_NODE_INDEX/$CI_NODE_TOTAL $GRADLE_ARGS --continue diff --git a/build.gradle.kts b/build.gradle.kts index 3d1021693bb..5c4fee0a62f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -83,10 +83,6 @@ allprojects { dependsOn(tasks.withType()) } - // Temurin 11/21 on Linux arm64 SIGSEGVs in SystemDictionary::define_instance_class - // during CDS shared-class restore. GRADLE_OPTS / org.gradle.jvmargs only reaches the - // Gradle daemon, so every forked JVM (Test executor, JavaCompile worker daemon when - // the toolchain differs from the daemon's JDK) must disable CDS on its own. val isLinuxArm64 = HostPlatform.isLinuxArm64() tasks.configureEach { @@ -99,11 +95,13 @@ allprojects { "-XX:HeapDumpPath=/tmp" ) if (isLinuxArm64) { + // Disable CDS to avoid SIGSEGVs on Linux arm64. jvmArgs("-Xshare:off") } } } + // Disable CDS to avoid SIGSEGVs on Linux arm64. if (isLinuxArm64) { tasks.withType().configureEach { options.forkOptions.jvmArgs?.add("-Xshare:off") diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt index 3f70bac7dec..839b41e0960 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/InstrumentPostProcessingAction.kt @@ -75,7 +75,7 @@ abstract class InstrumentPostProcessingAction @Inject constructor( forkOptions { setExecutable(javaLauncher.executablePath.asFile.absolutePath) if (HostPlatform.isLinuxArm64()) { - // Temurin on the arm64 Linux can crash during CDS shared-class restore; + // Disable CDS to avoid SIGSEGVs on Linux arm64. jvmArgs("-Xshare:off") } } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt index 08d42673298..76917c6a6c7 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt @@ -104,7 +104,7 @@ abstract class MuzzleTask @Inject constructor( jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") } if (HostPlatform.isLinuxArm64()) { - // Temurin on the arm64 Linux can crash during CDS shared-class restore; + // Disable CDS to avoid SIGSEGVs on Linux arm64. jvmArgs("-Xshare:off") } executable(javaLauncher.executablePath) diff --git a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts index dfe3cfa52c2..41868d093d1 100644 --- a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts +++ b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts @@ -81,9 +81,8 @@ private fun Test.configureTestJvm(extension: TestJvmConstraintsExtension) { extension.allowReflectiveAccessToJdk ) - // Fix for arm64 Linux ByteBuddy error: + // Fix for Linux arm64 ByteBuddy error: // "Could not self-attach to current VM using external process" - // Why it is needed on arm64: probably arm64 GitLab runners has stricter rules applied. if (HostPlatform.isLinuxArm64()) { conditionalJvmArgs( JavaVersion.VERSION_1_9, diff --git a/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy b/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy index 1c86d404784..746f57577c8 100644 --- a/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy +++ b/dd-java-agent/instrumentation/aerospike-4.0/src/test/groovy/datadog/trace/instrumentation/aerospike4/AerospikeBaseTest.groovy @@ -25,7 +25,7 @@ abstract class AerospikeBaseTest extends VersionedNamingTestBase { int aerospikePort = 3000 def setup() throws Exception { - // arm64 supported since ce-6.2.0.2 + // Linux arm64 supported since `ce-6.2.0.2` aerospike = new GenericContainer('aerospike:ce-6.2.0.2') .withExposedPorts(3000) // proto-fd-max default is 15000, but container default is 1024. diff --git a/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy b/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy index 4fb72863371..06d1b213d9d 100644 --- a/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy @@ -33,50 +33,63 @@ import org.testcontainers.containers.PostgreSQLContainer import org.testcontainers.utility.DockerImageName import spock.lang.Shared -abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { - static final String POSTGRESQL = "postgresql" - static final String MYSQL = "mysql" - static final String SQLSERVER = "sqlserver" - static final String ORACLE = "oracle" +enum DbType { + POSTGRESQL("postgresql"), + MYSQL("mysql"), + SQLSERVER("sqlserver"), + ORACLE("oracle") + + private final String name + DbType(String name) { + this.name = name + } + + @Override + String toString() { + return name + } +} + +abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { @Shared - private Map dbName = [ - (POSTGRESQL): "jdbcUnitTest", - (MYSQL) : "jdbcUnitTest", - (SQLSERVER) : "master", - (ORACLE) : "freepdb1", + private Map dbName = [ + (DbType.POSTGRESQL): "jdbcUnitTest", + (DbType.MYSQL) : "jdbcUnitTest", + (DbType.SQLSERVER) : "master", + (DbType.ORACLE) : "freepdb1", ] @Shared - private Map jdbcUrls = [ - (POSTGRESQL) : "jdbc:postgresql://localhost:5432/" + dbName.get(POSTGRESQL), - (MYSQL) : "jdbc:mysql://localhost:3306/" + dbName.get(MYSQL), - (SQLSERVER) : "jdbc:sqlserver://localhost:1433/" + dbName.get(SQLSERVER), - (ORACLE) : "jdbc:oracle:thin:@//localhost:1521/" + dbName.get(ORACLE), + private Map jdbcUrls = [ + (DbType.POSTGRESQL) : "jdbc:postgresql://localhost:5432/" + dbName.get(DbType.POSTGRESQL), + (DbType.MYSQL) : "jdbc:mysql://localhost:3306/" + dbName.get(DbType.MYSQL), + (DbType.SQLSERVER) : "jdbc:sqlserver://localhost:1433/" + dbName.get(DbType.SQLSERVER), + (DbType.ORACLE) : "jdbc:oracle:thin:@//localhost:1521/" + dbName.get(DbType.ORACLE), ] @Shared - private Map jdbcDriverClassNames = [ - (POSTGRESQL): "org.postgresql.Driver", - (MYSQL) : "com.mysql.jdbc.Driver", - (SQLSERVER) : "com.microsoft.sqlserver.jdbc.SQLServerDriver", - (ORACLE) : "oracle.jdbc.OracleDriver", + private Map jdbcDriverClassNames = [ + (DbType.POSTGRESQL): "org.postgresql.Driver", + (DbType.MYSQL) : "com.mysql.jdbc.Driver", + (DbType.SQLSERVER) : "com.microsoft.sqlserver.jdbc.SQLServerDriver", + (DbType.ORACLE) : "oracle.jdbc.OracleDriver", ] @Shared - private Map jdbcUserNames = [ - (POSTGRESQL): "sa", - (MYSQL) : "sa", - (SQLSERVER) : "sa", - (ORACLE) : "testuser", + private Map jdbcUserNames = [ + (DbType.POSTGRESQL): "sa", + (DbType.MYSQL) : "sa", + (DbType.SQLSERVER) : "sa", + (DbType.ORACLE) : "testuser", ] @Shared - private Map jdbcPasswords = [ - (MYSQL) : "sa", - (POSTGRESQL): "sa", - (SQLSERVER) : "Datad0g_", - (ORACLE) : "testPassword", + private Map jdbcPasswords = [ + (DbType.MYSQL) : "sa", + (DbType.POSTGRESQL): "sa", + (DbType.SQLSERVER) : "Datad0g_", + (DbType.ORACLE) : "testPassword", ] @Shared @@ -90,35 +103,99 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { // JDBC Connection pool name (i.e. HikariCP) -> Map @Shared - private Map> cpDatasources = new HashMap<>() + private Map> cpDatasources = new HashMap<>() - private static boolean dockerImageSupported(String db) { - return !(db == SQLSERVER && OperatingSystem.isArm64() && OperatingSystem.isLinux()) + private static boolean dockerImageSupported(DbType db) { + // MS SQL Server has no arm64 images. + return !(db == DbType.SQLSERVER && OperatingSystem.isArm64() && OperatingSystem.isLinux()) } - def peerConnectionProps(String db){ + def peerConnectionProps(DbType db){ def props = new Properties() props.setProperty("user", jdbcUserNames.get(db)) props.setProperty("password", jdbcPasswords.get(db)) return props } - protected getDbType(String dbType){ - return dbType + protected String getDbType(DbType dbType){ + return dbType.toString() } - def prepareConnectionPoolDatasources() { - String[] connectionPoolNames = ["tomcat", "hikari", "c3p0",] - connectionPoolNames.each { cpName -> - Map dbDSMapping = new HashMap<>() - jdbcUrls.each { dbType, jdbcUrl -> - dbDSMapping.put(dbType, createDS(cpName, dbType, jdbcUrl)) - } - cpDatasources.put(cpName, dbDSMapping) + private String jdbcUrlFor(DbType db) { + startContainer(db) + return jdbcUrls.get(db) + } + + private void startContainer(DbType db) { + switch (db) { + case DbType.POSTGRESQL: + startPostgres() + return + case DbType.MYSQL: + startMysql() + return + case DbType.SQLSERVER: + startSqlserver() + return + case DbType.ORACLE: + startOracle() + return + } + + throw new IllegalArgumentException("Unsupported database: ${db}") + } + + private void startPostgres() { + if (postgres != null) { + return + } + + postgres = new PostgreSQLContainer("postgres:11.2") + .withDatabaseName(dbName.get(DbType.POSTGRESQL)).withUsername(jdbcUserNames.get(DbType.POSTGRESQL)).withPassword(jdbcPasswords.get(DbType.POSTGRESQL)) + postgres.start() + PortUtils.waitForPortToOpen(postgres.getHost(), postgres.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT), 5, TimeUnit.SECONDS) + jdbcUrls.put(DbType.POSTGRESQL, "${postgres.getJdbcUrl()}") + } + + private void startMysql() { + if (mysql != null) { + return + } + + mysql = new MySQLContainer("mysql:8.0") + .withDatabaseName(dbName.get(DbType.MYSQL)).withUsername(jdbcUserNames.get(DbType.MYSQL)).withPassword(jdbcPasswords.get(DbType.MYSQL)) + // https://github.com/testcontainers/testcontainers-java/issues/914 + mysql.addParameter("TC_MY_CNF", null) + mysql.start() + PortUtils.waitForPortToOpen(mysql.getHost(), mysql.getMappedPort(MySQLContainer.MYSQL_PORT), 5, TimeUnit.SECONDS) + jdbcUrls.put(DbType.MYSQL, "${mysql.getJdbcUrl()}") + } + + private void startSqlserver() { + if (sqlserver != null) { + return + } + + sqlserver = new MSSQLServerContainer(MSSQLServerContainer.IMAGE).acceptLicense().withPassword(jdbcPasswords.get(DbType.SQLSERVER)) + sqlserver.start() + PortUtils.waitForPortToOpen(sqlserver.getHost(), sqlserver.getMappedPort(MSSQLServerContainer.MS_SQL_SERVER_PORT), 5, TimeUnit.SECONDS) + jdbcUrls.put(DbType.SQLSERVER, "${sqlserver.getJdbcUrl()};DatabaseName=${dbName.get(DbType.SQLSERVER)}") + } + + private void startOracle() { + if (oracle != null) { + return } + + // Earlier Oracle version images (oracle-xe) don't work on arm64 + DockerImageName oracleImage = DockerImageName.parse("gvenzl/oracle-free:23.5-slim-faststart").asCompatibleSubstituteFor("gvenzl/oracle-xe") + oracle = new OracleContainer(oracleImage) + .withStartupTimeout(Duration.ofMinutes(5)).withUsername(jdbcUserNames.get(DbType.ORACLE)).withPassword(jdbcPasswords.get(DbType.ORACLE)) + oracle.start() + jdbcUrls.put(DbType.ORACLE, "${oracle.getJdbcUrl()}".replace("xepdb1", dbName.get(DbType.ORACLE))) } - def createTomcatDS(String dbType, String jdbcUrl) { + def createTomcatDS(DbType dbType, String jdbcUrl) { DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource() ds.setUrl(jdbcUrl) ds.setDriverClassName(jdbcDriverClassNames.get(dbType)) @@ -132,7 +209,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { return ds } - def createHikariDS(String dbType, String jdbcUrl) { + def createHikariDS(DbType dbType, String jdbcUrl) { HikariConfig config = new HikariConfig() config.setJdbcUrl(jdbcUrl) String username = jdbcUserNames.get(dbType) @@ -148,11 +225,10 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { return new HikariDataSource(config) } - def createC3P0DS(String dbType, String jdbcUrl) { + def createC3P0DS(DbType dbType, String jdbcUrl) { DataSource ds = new ComboPooledDataSource() ds.setDriverClass(jdbcDriverClassNames.get(dbType)) - def jdbcUrlToSet = dbType == "derby" ? jdbcUrl + ";create=true" : jdbcUrl - ds.setJdbcUrl(jdbcUrlToSet) + ds.setJdbcUrl(jdbcUrl) String username = jdbcUserNames.get(dbType) if (username != null) { ds.setUser(username) @@ -162,13 +238,9 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { return ds } - def createDS(String connectionPoolName, String dbType, String jdbcUrl) { + def createDS(String connectionPoolName, DbType dbType, String jdbcUrl) { DataSource ds = null - if (!dockerImageSupported(dbType)) { - return ds - } - if (connectionPoolName == "tomcat") { ds = createTomcatDS(dbType, jdbcUrl) } @@ -181,6 +253,21 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { return ds } + private DataSource dataSourceFor(String pool, DbType db) { + Map dbDatasources = cpDatasources.get(pool) + if (dbDatasources == null) { + dbDatasources = new HashMap<>() + cpDatasources.put(pool, dbDatasources) + } + + DataSource datasource = dbDatasources.get(db) + if (datasource == null) { + datasource = createDS(pool, db, jdbcUrlFor(db)) + dbDatasources.put(db, datasource) + } + return datasource + } + @Override void configurePreAgent() { super.configurePreAgent() @@ -189,42 +276,6 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { injectSysConfig("dd.integration.jdbc-datasource.enabled", "true") } - def setupSpec() { - // POSTGRESQL - postgres = new PostgreSQLContainer("postgres:11.2") - .withDatabaseName(dbName.get(POSTGRESQL)).withUsername(jdbcUserNames.get(POSTGRESQL)).withPassword(jdbcPasswords.get(POSTGRESQL)) - postgres.start() - PortUtils.waitForPortToOpen(postgres.getHost(), postgres.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT), 5, TimeUnit.SECONDS) - jdbcUrls.put(POSTGRESQL, "${postgres.getJdbcUrl()}") - - // MYSQL - mysql = new MySQLContainer("mysql:8.0") - .withDatabaseName(dbName.get(MYSQL)).withUsername(jdbcUserNames.get(MYSQL)).withPassword(jdbcPasswords.get(MYSQL)) - // https://github.com/testcontainers/testcontainers-java/issues/914 - mysql.addParameter("TC_MY_CNF", null) - mysql.start() - PortUtils.waitForPortToOpen(mysql.getHost(), mysql.getMappedPort(MySQLContainer.MYSQL_PORT), 5, TimeUnit.SECONDS) - jdbcUrls.put(MYSQL, "${mysql.getJdbcUrl()}") - - // SQLSERVER - if (dockerImageSupported(SQLSERVER)) { - sqlserver = new MSSQLServerContainer(MSSQLServerContainer.IMAGE).acceptLicense().withPassword(jdbcPasswords.get(SQLSERVER)) - sqlserver.start() - PortUtils.waitForPortToOpen(sqlserver.getHost(), sqlserver.getMappedPort(MSSQLServerContainer.MS_SQL_SERVER_PORT), 5, TimeUnit.SECONDS) - jdbcUrls.put(SQLSERVER, "${sqlserver.getJdbcUrl()};DatabaseName=${dbName.get(SQLSERVER)}") - } - - // ORACLE - // Earlier Oracle version images (oracle-xe) don't work on arm64 - DockerImageName oracleImage = DockerImageName.parse("gvenzl/oracle-free:23.5-slim-faststart").asCompatibleSubstituteFor("gvenzl/oracle-xe") - oracle = new OracleContainer(oracleImage) - .withStartupTimeout(Duration.ofMinutes(5)).withUsername(jdbcUserNames.get(ORACLE)).withPassword(jdbcPasswords.get(ORACLE)) - oracle.start() - jdbcUrls.put(ORACLE, "${oracle.getJdbcUrl()}".replace("xepdb1", dbName.get(ORACLE))) - - prepareConnectionPoolDatasources() - } - def cleanupSpec() { cpDatasources.values().each { it.values().each { datasource -> @@ -255,7 +306,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { def addDbmTag = dbmTraceInjected() resultSet.next() resultSet.getInt(1) == 3 - if (driver == POSTGRESQL || driver == MYSQL || driver == ORACLE || !addDbmTag) { + if (driver == DbType.POSTGRESQL || driver == DbType.MYSQL || driver == DbType.ORACLE || !addDbmTag) { assertTraces(1) { trace(2) { basicSpan(it, "parent") @@ -354,22 +405,22 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { where: driver | pool | renameService | query | operation | obfuscatedQuery | usingHikari - MYSQL | null | false | "SELECT 3" | "SELECT" | "SELECT ?" | false - POSTGRESQL | null | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | false - SQLSERVER | null | false | "SELECT 3" | "SELECT" | "SELECT ?" | false - ORACLE | null | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false - MYSQL | "tomcat" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false - POSTGRESQL | "tomcat" | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | false - SQLSERVER | "tomcat" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false - ORACLE | "tomcat" | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false - MYSQL | "hikari" | false | "SELECT 3" | "SELECT" | "SELECT ?" | true - POSTGRESQL | "hikari" | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | true - SQLSERVER | "hikari" | false | "SELECT 3" | "SELECT" | "SELECT ?" | true - ORACLE | "hikari" | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | true - MYSQL | "c3p0" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false - POSTGRESQL | "c3p0" | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | false - SQLSERVER | "c3p0" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false - ORACLE | "c3p0" | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false + DbType.MYSQL | null | false | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.POSTGRESQL | null | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | false + DbType.SQLSERVER | null | false | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.ORACLE | null | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false + DbType.MYSQL | "tomcat" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.POSTGRESQL | "tomcat" | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | false + DbType.SQLSERVER | "tomcat" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.ORACLE | "tomcat" | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false + DbType.MYSQL | "hikari" | false | "SELECT 3" | "SELECT" | "SELECT ?" | true + DbType.POSTGRESQL | "hikari" | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | true + DbType.SQLSERVER | "hikari" | false | "SELECT 3" | "SELECT" | "SELECT ?" | true + DbType.ORACLE | "hikari" | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | true + DbType.MYSQL | "c3p0" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.POSTGRESQL | "c3p0" | false | "SELECT 3 FROM pg_user" | "SELECT" | "SELECT ? FROM pg_user" | false + DbType.SQLSERVER | "c3p0" | false | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.ORACLE | "c3p0" | false | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false } def "prepared statement execute on #driver with #pool generates a span"() { @@ -388,7 +439,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { resultSet.next() resultSet.getInt(1) == 3 def addDbmTag = dbmTraceInjected() - if (driver == SQLSERVER && addDbmTag){ + if (driver == DbType.SQLSERVER && addDbmTag){ assertTraces(1) { trace(3) { basicSpan(it, "parent") @@ -471,9 +522,9 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { if (usingHikari) { "$Tags.DB_POOL_NAME" String } - if (this.dbmTracePreparedStatements(this.getDbType(driver))){ + if (this.dbmTracePreparedStatements(driver)){ "$InstrumentationTags.DBM_TRACE_INJECTED" true - if (driver == POSTGRESQL) { + if (driver == DbType.POSTGRESQL) { "$InstrumentationTags.INSTRUMENTATION_TIME_MS" Long } } @@ -491,22 +542,22 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { where: driver | pool | query | operation | obfuscatedQuery | usingHikari - MYSQL | null | "SELECT 3" | "SELECT" | "SELECT ?" | false - POSTGRESQL | null | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | false - SQLSERVER | null | "SELECT 3" | "SELECT" | "SELECT ?" | false - ORACLE | null | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false - MYSQL | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" | false - POSTGRESQL | "tomcat" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | false - SQLSERVER | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" | false - ORACLE | "tomcat" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false - MYSQL | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" | true - POSTGRESQL | "hikari" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | true - SQLSERVER | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" | true - ORACLE | "hikari" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | true - MYSQL | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" | false - POSTGRESQL | "c3p0" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | false - SQLSERVER | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" | false - ORACLE | "c3p0" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false + DbType.MYSQL | null | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.POSTGRESQL | null | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | false + DbType.SQLSERVER | null | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.ORACLE | null | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false + DbType.MYSQL | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.POSTGRESQL | "tomcat" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | false + DbType.SQLSERVER | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.ORACLE | "tomcat" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false + DbType.MYSQL | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" | true + DbType.POSTGRESQL | "hikari" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | true + DbType.SQLSERVER | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" | true + DbType.ORACLE | "hikari" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | true + DbType.MYSQL | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.POSTGRESQL | "c3p0" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" | false + DbType.SQLSERVER | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" | false + DbType.ORACLE | "c3p0" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" | false } def "prepared statement query on #driver with #pool generates a span"() { @@ -525,7 +576,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { resultSet.getInt(1) == 3 def addDbmTag = dbmTraceInjected() - if (driver == SQLSERVER && addDbmTag){ + if (driver == DbType.SQLSERVER && addDbmTag){ assertTraces(1) { trace(3) { basicSpan(it, "parent") @@ -612,7 +663,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { } if (this.dbmTracePreparedStatements(driver)){ "$InstrumentationTags.DBM_TRACE_INJECTED" true - if (driver == POSTGRESQL) { + if (driver == DbType.POSTGRESQL) { "$InstrumentationTags.INSTRUMENTATION_TIME_MS" Long } } @@ -630,22 +681,22 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { where: driver | pool | query | operation | obfuscatedQuery - MYSQL | null | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | null | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | null | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | null | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" - MYSQL | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | "tomcat" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | "tomcat" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" - MYSQL | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | "hikari" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | "hikari" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" - MYSQL | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | "c3p0" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | "c3p0" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" + DbType.MYSQL | null | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | null | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | null | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | null | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" + DbType.MYSQL | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | "tomcat" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | "tomcat" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" + DbType.MYSQL | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | "hikari" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | "hikari" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" + DbType.MYSQL | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | "c3p0" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | "c3p0" | "SELECT 3 FROM dual" | "SELECT" | "SELECT ? FROM dual" } def "prepared call on #driver with #pool generates a span"() { @@ -663,7 +714,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { resultSet.next() resultSet.getInt(1) == 3 def addDbmTag = dbmTraceInjected() - if (driver == SQLSERVER && addDbmTag){ + if (driver == DbType.SQLSERVER && addDbmTag){ assertTraces(1) { trace(3) { basicSpan(it, "parent") @@ -743,9 +794,9 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { if (pool == "hikari") { "$Tags.DB_POOL_NAME" String } - if (this.dbmTracePreparedStatements(this.getDbType(driver))){ + if (this.dbmTracePreparedStatements(driver)){ "$InstrumentationTags.DBM_TRACE_INJECTED" true - if (driver == POSTGRESQL) { + if (driver == DbType.POSTGRESQL) { "$InstrumentationTags.INSTRUMENTATION_TIME_MS" Long } } @@ -762,22 +813,22 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { where: driver | pool | query | operation | obfuscatedQuery - MYSQL | null | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | null | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | null | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | null | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" - MYSQL | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | "tomcat" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | "tomcat" | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" - MYSQL | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | "hikari" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | "hikari" | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" - MYSQL | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" - POSTGRESQL | "c3p0" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" - SQLSERVER | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" - ORACLE | "c3p0" | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" + DbType.MYSQL | null | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | null | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | null | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | null | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" + DbType.MYSQL | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | "tomcat" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | "tomcat" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | "tomcat" | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" + DbType.MYSQL | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | "hikari" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | "hikari" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | "hikari" | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" + DbType.MYSQL | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.POSTGRESQL | "c3p0" | "SELECT 3 from pg_user" | "SELECT" | "SELECT ? from pg_user" + DbType.SQLSERVER | "c3p0" | "SELECT 3" | "SELECT" | "SELECT ?" + DbType.ORACLE | "c3p0" | "SELECT 3 from DUAL" | "SELECT" | "SELECT ? from DUAL" } def "statement update on #driver with #pool generates a span"() { @@ -795,7 +846,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { then: def addDbmTag = dbmTraceInjected() statement.updateCount == 0 - if (driver == POSTGRESQL || driver == MYSQL || driver == ORACLE || !dbmTraceInjected()) { + if (driver == DbType.POSTGRESQL || driver == DbType.MYSQL || driver == DbType.ORACLE || !dbmTraceInjected()) { assertTraces(1) { trace(2) { basicSpan(it, "parent") @@ -899,22 +950,22 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { where: driver | pool | query | operation - MYSQL | null | "CREATE TEMPORARY TABLE s_test_ (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - POSTGRESQL | null | "CREATE TEMPORARY TABLE s_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - SQLSERVER | null | "CREATE TABLE #s_test_ (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - ORACLE | null | "CREATE GLOBAL TEMPORARY TABLE s_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - MYSQL | "tomcat" | "CREATE TEMPORARY TABLE s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - POSTGRESQL | "tomcat" | "CREATE TEMPORARY TABLE s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - SQLSERVER | "tomcat" | "CREATE TABLE #s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - ORACLE | "tomcat" | "CREATE GLOBAL TEMPORARY TABLE s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - MYSQL | "hikari" | "CREATE TEMPORARY TABLE s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - POSTGRESQL | "hikari" | "CREATE TEMPORARY TABLE s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - SQLSERVER | "hikari" | "CREATE TABLE #s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - ORACLE | "hikari" | "CREATE GLOBAL TEMPORARY TABLE s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - MYSQL | "c3p0" | "CREATE TEMPORARY TABLE s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - POSTGRESQL | "c3p0" | "CREATE TEMPORARY TABLE s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - SQLSERVER | "c3p0" | "CREATE TABLE #s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" - ORACLE | "c3p0" | "CREATE GLOBAL TEMPORARY TABLE s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.MYSQL | null | "CREATE TEMPORARY TABLE s_test_ (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.POSTGRESQL | null | "CREATE TEMPORARY TABLE s_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.SQLSERVER | null | "CREATE TABLE #s_test_ (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.ORACLE | null | "CREATE GLOBAL TEMPORARY TABLE s_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.MYSQL | "tomcat" | "CREATE TEMPORARY TABLE s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.POSTGRESQL | "tomcat" | "CREATE TEMPORARY TABLE s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.SQLSERVER | "tomcat" | "CREATE TABLE #s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.ORACLE | "tomcat" | "CREATE GLOBAL TEMPORARY TABLE s_tomcat_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.MYSQL | "hikari" | "CREATE TEMPORARY TABLE s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.POSTGRESQL | "hikari" | "CREATE TEMPORARY TABLE s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.SQLSERVER | "hikari" | "CREATE TABLE #s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.ORACLE | "hikari" | "CREATE GLOBAL TEMPORARY TABLE s_hikari_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.MYSQL | "c3p0" | "CREATE TEMPORARY TABLE s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.POSTGRESQL | "c3p0" | "CREATE TEMPORARY TABLE s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.SQLSERVER | "c3p0" | "CREATE TABLE #s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" + DbType.ORACLE | "c3p0" | "CREATE GLOBAL TEMPORARY TABLE s_c3p0_test (id INTEGER not NULL, PRIMARY KEY ( id ))" | "CREATE" } @@ -940,14 +991,14 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { where: driver | pool | query - POSTGRESQL | "hikari" | "{ ? = call upper( ? ) }" - MYSQL | "hikari" | "{ ? = call upper( ? ) }" - POSTGRESQL | "tomcat" | "{ ? = call upper( ? ) }" - MYSQL | "tomcat" | "{ ? = call upper( ? ) }" - POSTGRESQL | "c3p0" | "{ ? = call upper( ? ) }" - MYSQL | "c3p0" | "{ ? = call upper( ? ) }" - POSTGRESQL | null | "{ ? = call upper( ? ) }" - MYSQL | null | "{ ? = call upper( ? ) }" + DbType.POSTGRESQL | "hikari" | "{ ? = call upper( ? ) }" + DbType.MYSQL | "hikari" | "{ ? = call upper( ? ) }" + DbType.POSTGRESQL | "tomcat" | "{ ? = call upper( ? ) }" + DbType.MYSQL | "tomcat" | "{ ? = call upper( ? ) }" + DbType.POSTGRESQL | "c3p0" | "{ ? = call upper( ? ) }" + DbType.MYSQL | "c3p0" | "{ ? = call upper( ? ) }" + DbType.POSTGRESQL | null | "{ ? = call upper( ? ) }" + DbType.MYSQL | null | "{ ? = call upper( ? ) }" } def "prepared procedure call on #driver with #pool does not hang"() { @@ -955,7 +1006,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { Connection connection = setupConnection(pool, driver) String createSql - if (driver == "postgresql") { + if (driver == DbType.POSTGRESQL) { createSql = """ CREATE OR REPLACE PROCEDURE dummy(inout res integer) @@ -964,7 +1015,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { SELECT 1; \$\$; """ - } else if (driver == "mysql") { + } else if (driver == DbType.MYSQL) { createSql = """ CREATE PROCEDURE IF NOT EXISTS dummy(inout res int) @@ -972,7 +1023,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { SELECT 1; END """ - } else if (driver == "sqlserver") { + } else if (driver == DbType.SQLSERVER) { createSql = """ CREATE PROCEDURE dummy @res integer output @@ -985,7 +1036,7 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { assert false } - if (driver.equals("postgresql") && connection.getMetaData().getDatabaseMajorVersion() <= 11) { + if (driver == DbType.POSTGRESQL && connection.getMetaData().getDatabaseMajorVersion() <= 11) { // Skip test for older versions of PG that don't support out on procedure return } @@ -1016,32 +1067,32 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { where: driver | pool | query - POSTGRESQL | "hikari" | "CALL dummy(?)" - MYSQL | "hikari" | "CALL dummy(?)" - SQLSERVER | "hikari" | "{CALL dummy(?)}" - POSTGRESQL | "tomcat" | "CALL dummy(?)" - MYSQL | "tomcat" | "{CALL dummy(?)}" - SQLSERVER | "tomcat" | "{CALL dummy(?)}" - POSTGRESQL | "c3p0" | "CALL dummy(?)" - MYSQL | "c3p0" | "CALL dummy(?)" - SQLSERVER | "c3p0" | "{CALL dummy(?)}" - POSTGRESQL | null | "CALL dummy(?)" - MYSQL | null | "CALL dummy(?)" - SQLSERVER | null | "{CALL dummy(?)}" + DbType.POSTGRESQL | "hikari" | "CALL dummy(?)" + DbType.MYSQL | "hikari" | "CALL dummy(?)" + DbType.SQLSERVER | "hikari" | "{CALL dummy(?)}" + DbType.POSTGRESQL | "tomcat" | "CALL dummy(?)" + DbType.MYSQL | "tomcat" | "{CALL dummy(?)}" + DbType.SQLSERVER | "tomcat" | "{CALL dummy(?)}" + DbType.POSTGRESQL | "c3p0" | "CALL dummy(?)" + DbType.MYSQL | "c3p0" | "CALL dummy(?)" + DbType.SQLSERVER | "c3p0" | "{CALL dummy(?)}" + DbType.POSTGRESQL | null | "CALL dummy(?)" + DbType.MYSQL | null | "CALL dummy(?)" + DbType.SQLSERVER | null | "{CALL dummy(?)}" } - Driver driverFor(String db) { + Driver driverFor(DbType db) { return newDriver(jdbcDriverClassNames.get(db)) } - Connection connectTo(String db, Properties properties) { - return connect(jdbcDriverClassNames.get(db), jdbcUrls.get(db), properties) + Connection connectTo(DbType db, Properties properties) { + return connect(jdbcDriverClassNames.get(db), jdbcUrlFor(db), properties) } - Connection setupConnection(String pool, String db) { + Connection setupConnection(String pool, DbType db) { assumeTrue(dockerImageSupported(db)) - def conn = pool ? cpDatasources.get(pool).get(db).getConnection() : connectTo(db, peerConnectionProps(db)) + def conn = pool ? dataSourceFor(pool, db).getConnection() : connectTo(db, peerConnectionProps(db)) // Clear any traces that pool or db can emmit on connection creation. TEST_WRITER.clear() @@ -1069,13 +1120,13 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { return null } - protected abstract String service(String dbType) + protected abstract String service(DbType dbType) protected abstract String operation(String dbType) protected abstract boolean dbmTraceInjected() - protected abstract boolean dbmTracePreparedStatements(String dbType) + protected abstract boolean dbmTracePreparedStatements(DbType dbType) } class RemoteJDBCInstrumentationV0Test extends RemoteJDBCInstrumentationTest { @@ -1086,8 +1137,8 @@ class RemoteJDBCInstrumentationV0Test extends RemoteJDBCInstrumentationTest { } @Override - protected String service(String dbType) { - return dbType + protected String service(DbType dbType) { + return dbType.toString() } @Override @@ -1101,7 +1152,7 @@ class RemoteJDBCInstrumentationV0Test extends RemoteJDBCInstrumentationTest { } @Override - protected boolean dbmTracePreparedStatements(String dbType) { + protected boolean dbmTracePreparedStatements(DbType dbType) { return false } } @@ -1114,7 +1165,7 @@ class RemoteJDBCInstrumentationV1ForkedTest extends RemoteJDBCInstrumentationTes } @Override - protected String service(String dbType) { + protected String service(DbType dbType) { return Config.get().getServiceName() } @@ -1129,14 +1180,14 @@ class RemoteJDBCInstrumentationV1ForkedTest extends RemoteJDBCInstrumentationTes } @Override - protected boolean dbmTracePreparedStatements(String dbType) { + protected boolean dbmTracePreparedStatements(DbType dbType) { return false } @Override - protected String getDbType(String dbType) { + protected String getDbType(DbType dbType) { final databaseNaming = new DatabaseNamingV1() - return databaseNaming.normalizedName(dbType) + return databaseNaming.normalizedName(dbType.toString()) } } @@ -1154,8 +1205,8 @@ class RemoteDBMTraceInjectedForkedTest extends RemoteJDBCInstrumentationTest { } @Override - protected boolean dbmTracePreparedStatements(String dbType){ - return dbType == ORACLE + protected boolean dbmTracePreparedStatements(DbType dbType){ + return dbType == DbType.ORACLE } @Override @@ -1164,7 +1215,7 @@ class RemoteDBMTraceInjectedForkedTest extends RemoteJDBCInstrumentationTest { } @Override - protected String service(String dbType) { + protected String service(DbType dbType) { return Config.get().getServiceName() } @@ -1174,16 +1225,16 @@ class RemoteDBMTraceInjectedForkedTest extends RemoteJDBCInstrumentationTest { } @Override - protected String getDbType(String dbType) { + protected String getDbType(DbType dbType) { final databaseNaming = new DatabaseNamingV1() - return databaseNaming.normalizedName(dbType) + return databaseNaming.normalizedName(dbType.toString()) } def "Oracle DBM comment contains instance name in dddbs and dddb, not generic type string"() { setup: // Use a query text unlikely to already be in v$sql cursor cache def markerQuery = "SELECT 1729 /* oracle-dbm-fix-verify */ FROM dual" - def conn = connectTo(ORACLE, peerConnectionProps(ORACLE)) + def conn = connectTo(DbType.ORACLE, peerConnectionProps(DbType.ORACLE)) when: def stmt = conn.createStatement() @@ -1237,7 +1288,7 @@ class RemoteDBMTraceInjectedForkedTestTracePreparedStatements extends RemoteJDBC } @Override - protected String service(String dbType) { + protected String service(DbType dbType) { return Config.get().getServiceName() } @@ -1247,13 +1298,13 @@ class RemoteDBMTraceInjectedForkedTestTracePreparedStatements extends RemoteJDBC } @Override - protected String getDbType(String dbType) { + protected String getDbType(DbType dbType) { final databaseNaming = new DatabaseNamingV1() - return databaseNaming.normalizedName(dbType) + return databaseNaming.normalizedName(dbType.toString()) } @Override - protected boolean dbmTracePreparedStatements(String dbType){ - return dbType == POSTGRESQL || dbType == ORACLE + protected boolean dbmTracePreparedStatements(DbType dbType){ + return dbType == DbType.POSTGRESQL || dbType == DbType.ORACLE } } diff --git a/dd-java-agent/instrumentation/protobuf-3.0/build.gradle b/dd-java-agent/instrumentation/protobuf-3.0/build.gradle index 34fd1e22816..cd5e818975f 100644 --- a/dd-java-agent/instrumentation/protobuf-3.0/build.gradle +++ b/dd-java-agent/instrumentation/protobuf-3.0/build.gradle @@ -28,7 +28,7 @@ protobuf { } } -// protobuf supports arm64 linux since 3.12.0, but it is not source-compatible with 3.0.0 +// TODO: protobuf supports Linux arm64 since `3.12.0`, but it is not source-compatible with 3.0.0 if (HostPlatform.isLinuxArm64()) { tasks.matching { it.name in [ diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java index 7947a8badf8..ae86574b0bc 100644 --- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java +++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java @@ -57,7 +57,7 @@ public static ProcessBuilder createProcessBuilder( "-Djava.util.prefs.userRoot=" + prefsDir)); if (OperatingSystem.isLinux() && OperatingSystem.isArm64()) { - // Temurin on the arm64 Linux can crash during CDS shared-class restore; + // Disable CDS to avoid SIGSEGVs on Linux arm64. baseCommand.add(1, "-Xshare:off"); } diff --git a/dd-smoke-tests/play-2.4/build.gradle b/dd-smoke-tests/play-2.4/build.gradle index 4645fd91e74..08d725ab095 100644 --- a/dd-smoke-tests/play-2.4/build.gradle +++ b/dd-smoke-tests/play-2.4/build.gradle @@ -101,8 +101,8 @@ tasks.withType(AbstractCopyTask).configureEach { if (HostPlatform.isLinuxArm64()) { tasks.named("compilePlayRoutes", RoutesCompile) { RoutesCompile task -> - // org.gradle.playframework.tasks.RoutesCompile does not expose worker fork options, but its - // worker JVM needs CDS disabled on Linux arm64 like the other forked JVMs in this build. + // org.gradle.playframework.tasks.RoutesCompile does not expose worker fork options, + // but its worker JVM needs CDS disabled on Linux arm64 to avoid SIGSEGVs. def workerExecutorField = RoutesCompile.getDeclaredField("workerExecutor") workerExecutorField.accessible = true diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy index 0d740d17e41..60ea121e4c9 100644 --- a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy @@ -253,9 +253,7 @@ abstract class AbstractSmokeTest extends ProcessManager { // ret += "-Ddd.dogstatsd.start-delay=0" } - // Disable CDS on Linux arm64: Temurin 11.0.31 / 21.0.10 hit a SIGSEGV during - // shared-class restore (ClassLoaderData::add_handle, Klass::class_loader) - // before any user code runs. + // Disable CDS to avoid SIGSEGVs on Linux arm64. if (OperatingSystem.isArm64() && OperatingSystem.isLinux()) { ret += "-Xshare:off" } diff --git a/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy b/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy index 471716b203d..4e8171dbc64 100644 --- a/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy +++ b/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy @@ -24,8 +24,7 @@ import spock.lang.Shared * * Note that the websphere related metrics will only arrive if our instrumentation is applied. */ -// IBM does not publish an arm64 build of icr.io/appcafe/websphere-traditional, and the -// arm64 CI runner has no amd64 emulation configured, so the container fails to start. +// There is no arm64 docker image for IBM icr.io/appcafe/websphere-traditional. @IgnoreIf({ OperatingSystem.isArm64() && OperatingSystem.isLinux() }) From e292092a3889e726b76a622c0197ab499d17826a Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 22 May 2026 14:44:37 -0400 Subject: [PATCH 14/24] Fixed review comments about `isArm64()` --- .../datadog/environment/OperatingSystem.java | 19 +++++++++---------- .../BuildIdExtractorIntegrationTest.java | 4 ++-- .../controller/EnvironmentChecker.java | 5 ++++- .../NettyExecutorInstrumentationTest.groovy | 3 ++- .../RemoteJDBCInstrumentationTest.groovy | 5 ++++- .../latestDepTest/groovy/RestletTest.groovy | 6 +++--- .../smoketest/ProcessBuilderHelper.java | 4 +++- .../smoketest/AbstractSmokeTest.groovy | 3 ++- .../smoketest/WebSphereJmxSmokeTest.groovy | 3 ++- 9 files changed, 31 insertions(+), 21 deletions(-) diff --git a/components/environment/src/main/java/datadog/environment/OperatingSystem.java b/components/environment/src/main/java/datadog/environment/OperatingSystem.java index 686bfca442d..7e64e6bdb33 100644 --- a/components/environment/src/main/java/datadog/environment/OperatingSystem.java +++ b/components/environment/src/main/java/datadog/environment/OperatingSystem.java @@ -1,6 +1,5 @@ package datadog.environment; -import static datadog.environment.OperatingSystem.Architecture.ARM64; import static datadog.environment.OperatingSystem.Type.LINUX; import static datadog.environment.OperatingSystem.Type.MACOS; import static datadog.environment.OperatingSystem.Type.WINDOWS; @@ -26,15 +25,6 @@ public final class OperatingSystem { private OperatingSystem() {} - /** - * Checks whether the architecture is arm64. - * - * @return @{@code true} if architecture is arm64, {@code false} otherwise. - */ - public static boolean isArm64() { - return ARCHITECTURE == ARM64; - } - /** * Checks whether the operating system is Linux based. * @@ -223,5 +213,14 @@ static Architecture current() { String property = SystemProperties.getOrDefault(OS_ARCH_PROPERTY, "").toLowerCase(ROOT); return Architecture.of(property); } + + /** + * Checks whether the architecture is arm64. + * + * @return {@code true} if architecture is arm64, {@code false} otherwise. + */ + public boolean isArm64() { + return this == ARM64; + } } } diff --git a/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java index da13cbca0b5..14c14a6a97d 100644 --- a/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java +++ b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java @@ -1,11 +1,11 @@ package datadog.crashtracking.buildid; +import static datadog.environment.OperatingSystem.architecture; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; -import datadog.environment.OperatingSystem; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -137,7 +137,7 @@ private static Stream elfBinaries() { @MethodSource("elfBinaries") void testElfBuildIdExtraction(String containerPath, String description) throws Exception { // TODO: check if arm64 can be supported too. - assumeFalse(OperatingSystem.isArm64(), "Skipping for arm64"); + assumeFalse(architecture().isArm64(), "Skipping for arm64"); Path localBinary = copyFromContainer(linuxContainer, containerPath); ElfBuildIdExtractor extractor = new ElfBuildIdExtractor(); diff --git a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java index 62beaeba443..be2553acade 100644 --- a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java +++ b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/EnvironmentChecker.java @@ -1,5 +1,7 @@ package com.datadog.profiling.controller; +import static datadog.environment.OperatingSystem.architecture; + import datadog.environment.JavaVirtualMachine; import datadog.environment.OperatingSystem; import datadog.environment.SystemProperties; @@ -236,12 +238,13 @@ private static boolean checkLoadLibrary(Path target, StringBuilder sb) { @SuppressForbidden private static boolean extractSoFromJar(Path target, StringBuilder sb) throws Exception { URL jarUrl = EnvironmentChecker.class.getProtectionDomain().getCodeSource().getLocation(); + String linuxArchFolder = architecture().isArm64() ? "/linux-arm64/" : "/linux-x64/"; try (JarFile jarFile = new JarFile(new File(jarUrl.toURI()))) { return jarFile.stream() .filter(e -> e.getName().contains("libjavaProfiler.so")) .filter( e -> - e.getName().contains(OperatingSystem.isArm64() ? "/linux-arm64/" : "/linux-x64/") + e.getName().contains(linuxArchFolder) && (!OperatingSystem.isMusl() || e.getName().contains("-musl"))) .findFirst() .map( diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy index 48b8267c5b8..727d8060c32 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy @@ -1,5 +1,6 @@ package executor +import static datadog.environment.OperatingSystem.architecture import static org.junit.jupiter.api.Assumptions.assumeTrue import datadog.environment.OperatingSystem @@ -22,7 +23,7 @@ import spock.lang.Shared // TODO: netty-all 4.1.9 only ships linux-x86_64 epoll native libraries. @IgnoreIf({ - OperatingSystem.isLinux() && OperatingSystem.isArm64() + OperatingSystem.isLinux() && architecture().isArm64() }) class NettyExecutorInstrumentationTest extends InstrumentationSpecification { diff --git a/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy b/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy index 06d1b213d9d..4d780134a1f 100644 --- a/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/jdbc/src/test/groovy/RemoteJDBCInstrumentationTest.groovy @@ -1,3 +1,4 @@ +import static datadog.environment.OperatingSystem.architecture import static datadog.trace.agent.test.utils.TraceUtils.basicSpan import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE @@ -107,7 +108,9 @@ abstract class RemoteJDBCInstrumentationTest extends VersionedNamingTestBase { private static boolean dockerImageSupported(DbType db) { // MS SQL Server has no arm64 images. - return !(db == DbType.SQLSERVER && OperatingSystem.isArm64() && OperatingSystem.isLinux()) + return !(db == DbType.SQLSERVER + && OperatingSystem.isLinux() + && architecture().isArm64()) } def peerConnectionProps(DbType db){ diff --git a/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy b/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy index 2c308efeb29..fe504f1a030 100644 --- a/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy +++ b/dd-java-agent/instrumentation/restlet-2.2/src/latestDepTest/groovy/RestletTest.groovy @@ -1,6 +1,6 @@ -import static datadog.environment.OperatingSystem.isArm64 -import static datadog.environment.OperatingSystem.isLinux +import static datadog.environment.OperatingSystem.architecture +import datadog.environment.OperatingSystem import org.restlet.Request import org.restlet.Response import org.restlet.data.Header @@ -12,7 +12,7 @@ class RestletTest extends RestletTestBase { @Override boolean testParallelRequest() { // TODO: Parallel processing is failing on Linux arm64. - return !(isLinux() && isArm64()) + return !(OperatingSystem.isLinux() && architecture().isArm64()) } @Override diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java index ae86574b0bc..c26e588c07c 100644 --- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java +++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java @@ -1,5 +1,7 @@ package datadog.smoketest; +import static datadog.environment.OperatingSystem.architecture; + import datadog.environment.OperatingSystem; import java.io.File; import java.nio.file.Path; @@ -56,7 +58,7 @@ public static ProcessBuilder createProcessBuilder( "-Ddd.version=99", "-Djava.util.prefs.userRoot=" + prefsDir)); - if (OperatingSystem.isLinux() && OperatingSystem.isArm64()) { + if (OperatingSystem.isLinux() && architecture().isArm64()) { // Disable CDS to avoid SIGSEGVs on Linux arm64. baseCommand.add(1, "-Xshare:off"); } diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy index 60ea121e4c9..ae1d2f6b6ef 100644 --- a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy @@ -1,5 +1,6 @@ package datadog.smoketest +import static datadog.environment.OperatingSystem.architecture import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer import static datadog.trace.api.ProtocolVersion.V0_4 import static datadog.trace.api.ProtocolVersion.V0_5 @@ -254,7 +255,7 @@ abstract class AbstractSmokeTest extends ProcessManager { } // Disable CDS to avoid SIGSEGVs on Linux arm64. - if (OperatingSystem.isArm64() && OperatingSystem.isLinux()) { + if (OperatingSystem.isLinux() && architecture().isArm64()) { ret += "-Xshare:off" } ret as String[] diff --git a/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy b/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy index 4e8171dbc64..dc3dfdd6efe 100644 --- a/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy +++ b/dd-smoke-tests/websphere-jmx/src/test/groovy/datadog/smoketest/WebSphereJmxSmokeTest.groovy @@ -1,5 +1,6 @@ package datadog.smoketest +import static datadog.environment.OperatingSystem.architecture import datadog.environment.OperatingSystem import java.time.Duration @@ -26,7 +27,7 @@ import spock.lang.Shared */ // There is no arm64 docker image for IBM icr.io/appcafe/websphere-traditional. @IgnoreIf({ - OperatingSystem.isArm64() && OperatingSystem.isLinux() + OperatingSystem.isLinux() && architecture().isArm64() }) class WebSphereJmxSmokeTest extends AbstractSmokeTest { From 0bedeff4e0d4fad3e0d68eebf7d8d638b5bbe43a Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 22 May 2026 14:53:35 -0400 Subject: [PATCH 15/24] Fixed review comments about `ProcessBuilderHelper`. --- .../smoketest/ProcessBuilderHelper.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java index c26e588c07c..7bdc5ddfa24 100644 --- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java +++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/ProcessBuilderHelper.java @@ -46,25 +46,23 @@ public static ProcessBuilder createProcessBuilder( + System.nanoTime(); List baseCommand = - new ArrayList<>( - Arrays.asList( - javaPath(), - // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:5006", - "-Xmx" + System.getProperty("datadog.forkedMaxHeapSize", "1024M"), - "-Xms" + System.getProperty("datadog.forkedMinHeapSize", "64M"), - "-javaagent:" + agentShadowJar(), - "-XX:ErrorFile=/tmp/hs_err_pid%p.log", - "-Ddd.env=smoketest", - "-Ddd.version=99", - "-Djava.util.prefs.userRoot=" + prefsDir)); + Arrays.asList( + javaPath(), + // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:5006", + "-Xmx" + System.getProperty("datadog.forkedMaxHeapSize", "1024M"), + "-Xms" + System.getProperty("datadog.forkedMinHeapSize", "64M"), + "-javaagent:" + agentShadowJar(), + "-XX:ErrorFile=/tmp/hs_err_pid%p.log", + "-Ddd.env=smoketest", + "-Ddd.version=99", + "-Djava.util.prefs.userRoot=" + prefsDir); + List command = new ArrayList<>(); + command.addAll(baseCommand); if (OperatingSystem.isLinux() && architecture().isArm64()) { // Disable CDS to avoid SIGSEGVs on Linux arm64. - baseCommand.add(1, "-Xshare:off"); + command.add(1, "-Xshare:off"); } - - List command = new ArrayList<>(); - command.addAll(baseCommand); command.addAll(additionalCommandParams); command.addAll(Arrays.asList("-cp", classpath, mainClassName)); command.addAll(Arrays.asList(params)); From a850d45a17df5ef7a0d3d05b32523eec7fde3f46 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 22 May 2026 16:28:30 -0400 Subject: [PATCH 16/24] Polishing GitLab script. --- .gitlab-ci.yml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6965d4c9980..7899db24f90 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -745,6 +745,8 @@ muzzle-dep-report: unprotect: true before_script: - git config --global --add safe.directory "$CI_PROJECT_DIR" + # Akka token added to SSM from https://account.akka.io/token + - export ORG_GRADLE_PROJECT_akkaRepositoryToken=$(aws ssm get-parameter --region us-east-1 --name ci.dd-trace-java.akka_repo_token --with-decryption --query "Parameter.Value" --out text) - export ORG_GRADLE_PROJECT_mavenRepositoryProxy=$MAVEN_REPOSITORY_PROXY - export ORG_GRADLE_PROJECT_gradlePluginProxy=$GRADLE_PLUGIN_PROXY - | @@ -755,14 +757,9 @@ muzzle-dep-report: org.gradle.java.installations.fromEnv=$JAVA_HOMES EOF - mkdir -p .gradle .mvn/caches - # The `dependency-$CACHE_TYPE` cache is populated by amd64's `populate_dep_cache` - # (running as root). arm64 runs as `non-root-user`, so when Gradle does `chmod 700` - # on the restored .gradle directory it fails with EPERM. Rewrite the tree under - # the runner user's ownership before invoking Gradle. Mirrors the dance in - # `.gradle_build` (.gitlab-ci.yml:239-247). - - cp -r .gradle .gradle-copy - - rm -rf .gradle - - mv .gradle-copy .gradle + # GitLab's cache helper restores .gradle as root, but we run as non-root-user (uid 1001), + # and Gradle does `chmod 700 .gradle` on startup which requires user ownership. + - sudo chown -R 1001:1001 .gradle - export GRADLE_USER_HOME=$(pwd)/.gradle - sed -i "s|https://repo.maven.apache.org/maven2/|$MAVEN_REPOSITORY_PROXY|g" .mvn/wrapper/maven-wrapper.properties - *normalize_node_index @@ -772,12 +769,22 @@ muzzle-dep-report: - export GRADLE_ARGS="--build-cache --stacktrace --no-daemon --parallel --max-workers=$GRADLE_WORKERS" - ./gradlew --version script: + - *gitlab_base_ref_params - ./gradlew $GRADLE_TARGET $GRADLE_PARAMS -PtestJvm=$testJvm -Pslot=$CI_NODE_INDEX/$CI_NODE_TOTAL $GRADLE_ARGS --continue after_script: + - *restore_pretest_env + - *set_datadog_api_keys + - *container_info - *cgroup_info + - source .gitlab/gitlab-utils.sh - gitlab_section_start "collect-reports" "Collecting reports" - .gitlab/collect_reports.sh + - .gitlab/collect_results.sh + - .gitlab/upload_ciapp.sh $CACHE_TYPE $testJvm - gitlab_section_end "collect-reports" + - .gitlab/count_tests.sh "$GRADLE_TARGET" "$testJvm" "./results" "./test_counts_${CI_JOB_ID}.json" + - URL_ENCODED_JOB_NAME=$(jq -rn --arg x "$CI_JOB_NAME" '$x|@uri') + - echo -e "${TEXT_BOLD}${TEXT_YELLOW}See test results in Datadog:${TEXT_CLEAR} https://app.datadoghq.com/ci/test/runs?query=test_level%3Atest%20%40test.service%3Add-trace-java%20%40ci.pipeline.id%3A${CI_PIPELINE_ID}%20%40ci.job.name%3A%22${URL_ENCODED_JOB_NAME}%22" artifacts: when: always paths: From 89df26a1f1107f3a3db59157ac69f5d3851de107 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 22 May 2026 16:34:28 -0400 Subject: [PATCH 17/24] Running on non default JDKs. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7899db24f90..304f15b330e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -728,7 +728,7 @@ muzzle-dep-report: - if: $testJvm =~ $DEFAULT_TEST_JVMS when: manual allow_failure: true - - if: '$NON_DEFAULT_JVMS == "true"' + - if: '$NON_DEFAULT_JVMS == "true" && $testJvm != "ibm8"' when: manual allow_failure: true cache: From 51d5ec009238bd4050dc16aaff13d67ee8f5fe90 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 22 May 2026 16:53:03 -0400 Subject: [PATCH 18/24] Fixed non-default JVMs. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 304f15b330e..1a6f1f94f46 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -709,7 +709,7 @@ muzzle-dep-report: - data_integrity_failure .test_job_arm64: - image: ${BUILDER_IMAGE_REPO}:${BUILDER_IMAGE_VERSION_PREFIX}base + image: ${BUILDER_IMAGE_REPO}:${BUILDER_IMAGE_VERSION_PREFIX}$testJvm tags: [ "docker-in-docker:arm64" ] stage: tests-arm64 needs: [] From eab7ecdff00eb7b230fc3a9fdbaff7376d412af8 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 22 May 2026 21:38:07 -0400 Subject: [PATCH 19/24] Workarounds for Oracle 8 and Semeru JDKs. --- .../environment/CommandLineHelper.java | 21 +++++++++++++++++++ .../datadog/environment/CommandLineTest.java | 15 +++++++++++-- .../smoketest/Java9ModulesSmokeTest.groovy | 9 ++++++++ .../writer/DDAgentWriterCombinedTest.groovy | 9 ++++++++ .../writer/DDIntakeWriterCombinedTest.groovy | 9 ++++++++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/components/environment/src/test/java/datadog/environment/CommandLineHelper.java b/components/environment/src/test/java/datadog/environment/CommandLineHelper.java index d2e17ba0150..28eaeb553f7 100644 --- a/components/environment/src/test/java/datadog/environment/CommandLineHelper.java +++ b/components/environment/src/test/java/datadog/environment/CommandLineHelper.java @@ -99,6 +99,27 @@ static RunArguments of(List jvmArgs, List cmdArgs) { arguments.cmdArgs = cmdArgs; return arguments; } + + /** + * Prepends {@code -XX:+UnlockExperimentalVMOptions} when the JVM options reference an + * experimental flag on the current JVM. Required for {@code -XX:+UseG1GC} on Oracle JDK 8 + * aarch64, where G1GC is shipped as experimental. + */ + RunArguments withUnlockExperimentalVMOptionsIfNeeded() { + if (!needsUnlockExperimentalVMOptions(jvmOptions)) { + return this; + } + List updated = new ArrayList<>(jvmOptions.size() + 1); + updated.add("-XX:+UnlockExperimentalVMOptions"); + updated.addAll(jvmOptions); + return RunArguments.of(updated, cmdArgs); + } + + private static boolean needsUnlockExperimentalVMOptions(List jvmOptions) { + return JavaVirtualMachine.isOracleJDK8() + && OperatingSystem.architecture().isArm64() + && jvmOptions.contains("-XX:+UseG1GC"); + } } static class Result extends RunArguments { diff --git a/components/environment/src/test/java/datadog/environment/CommandLineTest.java b/components/environment/src/test/java/datadog/environment/CommandLineTest.java index b1673b80a29..384bcd487e0 100644 --- a/components/environment/src/test/java/datadog/environment/CommandLineTest.java +++ b/components/environment/src/test/java/datadog/environment/CommandLineTest.java @@ -36,17 +36,25 @@ static Stream data() { of(emptyList(), emptyList()) ), arguments( - "JVM options only", + "JVM options only with G1GC", of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), emptyList()), of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), emptyList())), + arguments( + "JVM options only with ParallelGC", + of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), emptyList()), + of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), emptyList())), arguments( "Command arguments only", of(emptyList(), asList("arg1", "arg2")), of(emptyList(), asList("arg1", "arg2"))), arguments( - "Both JVM options and command arguments", + "Both JVM options and command arguments with G1GC", of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), asList("arg1", "arg2")), of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), asList("arg1", "arg2"))), + arguments( + "Both JVM options and command arguments with ParallelGC", + of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), asList("arg1", "arg2")), + of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), asList("arg1", "arg2"))), arguments( "JVM options from argfile", of(asList("-Dtest.property=value", argFile("carriage-return-separated")), asList("arg1", "arg2")), @@ -73,6 +81,9 @@ void testGetVmArguments(String useCase, RunArguments arguments, RunArguments exp throws Exception { // Skip unsupported test cases skipArgFileTestOnJava8(arguments); + // Unlock experimental options when needed (e.g. UseG1GC on Oracle JDK 8 aarch64) + arguments = arguments.withUnlockExperimentalVMOptionsIfNeeded(); + expectedArguments = expectedArguments.withUnlockExperimentalVMOptionsIfNeeded(); // Run test process Result result = forkAndRunWithArgs(arguments); // Check results diff --git a/dd-smoke-tests/java9-modules/src/test/groovy/datadog/smoketest/Java9ModulesSmokeTest.groovy b/dd-smoke-tests/java9-modules/src/test/groovy/datadog/smoketest/Java9ModulesSmokeTest.groovy index da1c10bd5c8..8272215b3fb 100644 --- a/dd-smoke-tests/java9-modules/src/test/groovy/datadog/smoketest/Java9ModulesSmokeTest.groovy +++ b/dd-smoke-tests/java9-modules/src/test/groovy/datadog/smoketest/Java9ModulesSmokeTest.groovy @@ -1,7 +1,16 @@ package datadog.smoketest +import static datadog.environment.OperatingSystem.architecture import static java.util.concurrent.TimeUnit.SECONDS +import datadog.environment.JavaVirtualMachine +import datadog.environment.OperatingSystem +import spock.lang.IgnoreIf + +// TODO: OpenJ9 (Semeru) on Linux arm64 fails on this test. +@IgnoreIf({ + OperatingSystem.isLinux() && architecture().isArm64() && JavaVirtualMachine.isJ9() +}) class Java9ModulesSmokeTest extends AbstractSmokeTest { // Estimate for the amount of time instrumentation plus some extra private static final int TIMEOUT_SECS = 30 diff --git a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy index 1659ab44da3..2a72eaf0780 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy @@ -1,5 +1,6 @@ package datadog.trace.common.writer +import static datadog.environment.OperatingSystem.architecture import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer import static datadog.trace.api.ProtocolVersion.V0_5 import static datadog.trace.api.config.GeneralConfig.EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED @@ -7,6 +8,8 @@ import static datadog.trace.common.writer.DDAgentWriter.BUFFER_SIZE import static datadog.trace.common.writer.ddagent.Prioritization.ENSURE_TRACE import datadog.communication.ddagent.DDAgentFeaturesDiscovery +import datadog.environment.JavaVirtualMachine +import datadog.environment.OperatingSystem import datadog.communication.http.OkHttpUtils import datadog.communication.serialization.ByteBufferConsumer import datadog.communication.serialization.FlushingBuffer @@ -38,6 +41,7 @@ import java.util.concurrent.Semaphore import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger import okhttp3.HttpUrl +import spock.lang.IgnoreIf import spock.lang.Timeout import spock.util.concurrent.PollingConditions @@ -193,6 +197,11 @@ class DDAgentWriterCombinedTest extends DDCoreSpecification { agentVersion << ["v0.3/traces", "v0.4/traces", "v0.5/traces"] } + // TODO: Oracle JDK 8 on linux-aarch64 crashes in PSPromotionManager under the heavy allocation + // pressure of this test. + @IgnoreIf({ + OperatingSystem.isLinux() && architecture().isArm64() && JavaVirtualMachine.isOracleJDK8() + }) @Timeout(30) def "test default buffer size for #agentVersion"() { setup: diff --git a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy index 966d4e91ecb..86784e2230e 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy @@ -1,6 +1,8 @@ package datadog.trace.common.writer import datadog.communication.http.OkHttpUtils +import datadog.environment.JavaVirtualMachine +import datadog.environment.OperatingSystem import datadog.communication.serialization.ByteBufferConsumer import datadog.communication.serialization.FlushingBuffer import datadog.communication.serialization.msgpack.MsgPackWriter @@ -24,6 +26,7 @@ import datadog.trace.core.propagation.PropagationTags import datadog.trace.core.test.DDCoreSpecification import datadog.trace.test.util.Flaky import okhttp3.HttpUrl +import spock.lang.IgnoreIf import spock.lang.Shared import spock.lang.Timeout import spock.util.concurrent.PollingConditions @@ -35,6 +38,7 @@ import java.util.concurrent.Semaphore import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger +import static datadog.environment.OperatingSystem.architecture import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer import static datadog.trace.common.writer.DDIntakeWriter.BUFFER_SIZE import static datadog.trace.common.writer.ddagent.Prioritization.ENSURE_TRACE @@ -185,6 +189,11 @@ class DDIntakeWriterCombinedTest extends DDCoreSpecification { trackType << [TrackType.CITESTCYCLE] } + // TODO: Oracle JDK 8 on linux-aarch64 crashes in PSPromotionManager under the heavy allocation + // pressure of this test. + @IgnoreIf({ + OperatingSystem.isLinux() && architecture().isArm64() && JavaVirtualMachine.isOracleJDK8() + }) @Timeout(30) def "test default buffer size for #trackType"() { setup: From fe65096e2aabab09686f3f20d7986cb0687d717d Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 24 May 2026 12:13:03 -0400 Subject: [PATCH 20/24] Testing Oracle 8 not crashed on arm64 without profiling. --- .../src/test/groovy/QueueTimingForkedTest.groovy | 11 +++++++++-- .../src/test/groovy/TaskUnwrappingForkedTest.groovy | 12 ++++++++++-- .../executor/ExecutorInstrumentationTest.groovy | 11 +++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy index 5e5c63bd95c..1be841dcf74 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy @@ -1,4 +1,5 @@ import datadog.environment.JavaVirtualMachine +import datadog.environment.OperatingSystem import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.agent.test.TestProfilingContextIntegration import datadog.trace.bootstrap.instrumentation.jfr.InstrumentationBasedProfiling @@ -11,11 +12,17 @@ import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace class QueueTimingForkedTest extends InstrumentationSpecification { + // Hypothesis check: Oracle JDK 8 on linux-aarch64 SIGSEGVs inside Parallel Old GC + // when the profiler is started in-process. Disable profiling on that platform to + // see whether the crash is profiling-related. See crash.md. + private static final String PROFILING_ENABLED = + String.valueOf(!(JavaVirtualMachine.isOracleJDK8() && OperatingSystem.architecture().isArm64())) + @Override protected void configurePreAgent() { // required for enabling the unwrapping instrumentation to get the relevant non-carrier class names - injectSysConfig("dd.profiling.enabled", "true") - injectSysConfig("dd.profiling.queueing.time.enabled", "true") + injectSysConfig("dd.profiling.enabled", PROFILING_ENABLED) + injectSysConfig("dd.profiling.queueing.time.enabled", PROFILING_ENABLED) InstrumentationBasedProfiling.enableInstrumentationBasedProfiling() super.configurePreAgent() } diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy index 8cb7159c4ec..0a823fe46a8 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy @@ -1,3 +1,5 @@ +import datadog.environment.JavaVirtualMachine +import datadog.environment.OperatingSystem import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.bootstrap.instrumentation.api.TaskWrapper @@ -7,10 +9,16 @@ import java.util.concurrent.FutureTask class TaskUnwrappingForkedTest extends InstrumentationSpecification { + // Hypothesis check: Oracle JDK 8 on linux-aarch64 SIGSEGVs inside Parallel Old GC + // when the profiler is started in-process. Disable profiling on that platform to + // see whether the crash is profiling-related. See crash.md. + private static final String PROFILING_ENABLED = + String.valueOf(!(JavaVirtualMachine.isOracleJDK8() && OperatingSystem.architecture().isArm64())) + @Override protected void configurePreAgent() { - injectSysConfig("dd.profiling.enabled", "true") - injectSysConfig("dd.profiling.queueing.time.enabled", "true") + injectSysConfig("dd.profiling.enabled", PROFILING_ENABLED) + injectSysConfig("dd.profiling.queueing.time.enabled", PROFILING_ENABLED) super.configurePreAgent() } diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy index 945a92c4e95..97eb277d979 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy @@ -1,6 +1,8 @@ package executor import com.google.common.util.concurrent.MoreExecutors +import datadog.environment.JavaVirtualMachine +import datadog.environment.OperatingSystem import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.api.Trace import datadog.trace.bootstrap.instrumentation.api.Tags @@ -497,7 +499,12 @@ class ExecutorInstrumentationLegacyForkedTest extends ExecutorInstrumentationTes class ExecutorInstrumentationQueueTimeForkedTest extends ExecutorInstrumentationTest { def setupSpec() { - System.setProperty("dd.profiling.enabled", "true") - System.setProperty("dd.profiling.queueing.time.enabled", "true") + // Hypothesis check: Oracle JDK 8 on linux-aarch64 SIGSEGVs inside Parallel Old GC + // when the profiler is started in-process. Disable profiling on that platform to + // see whether the crash is profiling-related. See crash.md. + String profilingEnabled = + String.valueOf(!(JavaVirtualMachine.isOracleJDK8() && OperatingSystem.architecture().isArm64())) + System.setProperty("dd.profiling.enabled", profilingEnabled) + System.setProperty("dd.profiling.queueing.time.enabled", profilingEnabled) } } From 0331109bb0e19b7b354a371d3d4e8d40d4a6c6c3 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 24 May 2026 15:44:58 -0400 Subject: [PATCH 21/24] Attempt to fix Oracle 8 crash on arm64. --- .../dd-trace-java.test-jvm-constraints.gradle.kts | 11 +++++++++++ .../src/test/groovy/QueueTimingForkedTest.groovy | 11 ++--------- .../src/test/groovy/TaskUnwrappingForkedTest.groovy | 12 ++---------- .../executor/ExecutorInstrumentationTest.groovy | 11 ++--------- 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts index 41868d093d1..19ba90cd96f 100644 --- a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts +++ b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts @@ -89,6 +89,17 @@ private fun Test.configureTestJvm(extension: TestJvmConstraintsExtension) { listOf("-Djdk.attach.allowAttachSelf=true") ) } + + // Mitigation for SIGSEGV in Parallel Old GC on Oracle JDK 8 / linux-aarch64 + // (InstanceKlass::oop_follow_contents in PSParallelCompact). Switching to Serial GC + // removes the crashing code path entirely. See crash.md. + if (HostPlatform.isLinuxArm64()) { + conditionalJvmArgs( + JavaVersion.VERSION_1_8, + listOf("-XX:+UseSerialGC"), + testJvmSpec.testJvmProperty.map { it == "8" || it == "oracle8" }.orElse(false) + ) + } } // Jacoco plugin is not applied on every project diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy index 1be841dcf74..5e5c63bd95c 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/QueueTimingForkedTest.groovy @@ -1,5 +1,4 @@ import datadog.environment.JavaVirtualMachine -import datadog.environment.OperatingSystem import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.agent.test.TestProfilingContextIntegration import datadog.trace.bootstrap.instrumentation.jfr.InstrumentationBasedProfiling @@ -12,17 +11,11 @@ import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace class QueueTimingForkedTest extends InstrumentationSpecification { - // Hypothesis check: Oracle JDK 8 on linux-aarch64 SIGSEGVs inside Parallel Old GC - // when the profiler is started in-process. Disable profiling on that platform to - // see whether the crash is profiling-related. See crash.md. - private static final String PROFILING_ENABLED = - String.valueOf(!(JavaVirtualMachine.isOracleJDK8() && OperatingSystem.architecture().isArm64())) - @Override protected void configurePreAgent() { // required for enabling the unwrapping instrumentation to get the relevant non-carrier class names - injectSysConfig("dd.profiling.enabled", PROFILING_ENABLED) - injectSysConfig("dd.profiling.queueing.time.enabled", PROFILING_ENABLED) + injectSysConfig("dd.profiling.enabled", "true") + injectSysConfig("dd.profiling.queueing.time.enabled", "true") InstrumentationBasedProfiling.enableInstrumentationBasedProfiling() super.configurePreAgent() } diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy index 0a823fe46a8..8cb7159c4ec 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/TaskUnwrappingForkedTest.groovy @@ -1,5 +1,3 @@ -import datadog.environment.JavaVirtualMachine -import datadog.environment.OperatingSystem import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.bootstrap.instrumentation.api.TaskWrapper @@ -9,16 +7,10 @@ import java.util.concurrent.FutureTask class TaskUnwrappingForkedTest extends InstrumentationSpecification { - // Hypothesis check: Oracle JDK 8 on linux-aarch64 SIGSEGVs inside Parallel Old GC - // when the profiler is started in-process. Disable profiling on that platform to - // see whether the crash is profiling-related. See crash.md. - private static final String PROFILING_ENABLED = - String.valueOf(!(JavaVirtualMachine.isOracleJDK8() && OperatingSystem.architecture().isArm64())) - @Override protected void configurePreAgent() { - injectSysConfig("dd.profiling.enabled", PROFILING_ENABLED) - injectSysConfig("dd.profiling.queueing.time.enabled", PROFILING_ENABLED) + injectSysConfig("dd.profiling.enabled", "true") + injectSysConfig("dd.profiling.queueing.time.enabled", "true") super.configurePreAgent() } diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy index 97eb277d979..945a92c4e95 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/test/groovy/executor/ExecutorInstrumentationTest.groovy @@ -1,8 +1,6 @@ package executor import com.google.common.util.concurrent.MoreExecutors -import datadog.environment.JavaVirtualMachine -import datadog.environment.OperatingSystem import datadog.trace.agent.test.InstrumentationSpecification import datadog.trace.api.Trace import datadog.trace.bootstrap.instrumentation.api.Tags @@ -499,12 +497,7 @@ class ExecutorInstrumentationLegacyForkedTest extends ExecutorInstrumentationTes class ExecutorInstrumentationQueueTimeForkedTest extends ExecutorInstrumentationTest { def setupSpec() { - // Hypothesis check: Oracle JDK 8 on linux-aarch64 SIGSEGVs inside Parallel Old GC - // when the profiler is started in-process. Disable profiling on that platform to - // see whether the crash is profiling-related. See crash.md. - String profilingEnabled = - String.valueOf(!(JavaVirtualMachine.isOracleJDK8() && OperatingSystem.architecture().isArm64())) - System.setProperty("dd.profiling.enabled", profilingEnabled) - System.setProperty("dd.profiling.queueing.time.enabled", profilingEnabled) + System.setProperty("dd.profiling.enabled", "true") + System.setProperty("dd.profiling.queueing.time.enabled", "true") } } From 9408976c26be53181f51564d0f660ed03e36623b Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 24 May 2026 15:50:51 -0400 Subject: [PATCH 22/24] Attempt to fix crashing play smoke tests on Linux arm64. --- dd-smoke-tests/play-2.4/build.gradle | 41 +------------ dd-smoke-tests/play-2.5/build.gradle | 1 + dd-smoke-tests/play-2.6/build.gradle | 1 + dd-smoke-tests/play-2.7/build.gradle | 1 + dd-smoke-tests/play-2.8-otel/build.gradle | 1 + .../play-2.8-split-routes/build.gradle | 1 + dd-smoke-tests/play-2.8/build.gradle | 1 + .../play-common/fix-play-linux-arm64.gradle | 58 +++++++++++++++++++ 8 files changed, 65 insertions(+), 40 deletions(-) create mode 100644 dd-smoke-tests/play-common/fix-play-linux-arm64.gradle diff --git a/dd-smoke-tests/play-2.4/build.gradle b/dd-smoke-tests/play-2.4/build.gradle index 08d725ab095..d035365979a 100644 --- a/dd-smoke-tests/play-2.4/build.gradle +++ b/dd-smoke-tests/play-2.4/build.gradle @@ -1,9 +1,3 @@ -import datadog.gradle.plugin.HostPlatform -import org.gradle.playframework.tasks.RoutesCompile -import org.gradle.playframework.tasks.internal.RoutesCompileWorkAction -import org.gradle.playframework.tools.internal.routes.DefaultRoutesCompileSpec -import org.gradle.playframework.tools.internal.routes.RoutesCompilerFactory - plugins { id 'org.gradle.playframework' } @@ -16,6 +10,7 @@ testJvmConstraints { } apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-routes.gradle" +apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle" def playVer = "2.4.11" def scalaVer = System.getProperty("scala.binary.version", /* default = */ "2.11") @@ -99,40 +94,6 @@ tasks.withType(AbstractCopyTask).configureEach { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } -if (HostPlatform.isLinuxArm64()) { - tasks.named("compilePlayRoutes", RoutesCompile) { RoutesCompile task -> - // org.gradle.playframework.tasks.RoutesCompile does not expose worker fork options, - // but its worker JVM needs CDS disabled on Linux arm64 to avoid SIGSEGVs. - def workerExecutorField = RoutesCompile.getDeclaredField("workerExecutor") - workerExecutorField.accessible = true - - task.actions.clear() - task.doLast { - def spec = new DefaultRoutesCompileSpec( - task.source.files, - task.outputDirectory.get().asFile, - task.javaProject, - task.namespaceReverseRouter.get(), - task.generateReverseRoutes.get(), - task.injectedRoutesGenerator.get(), - task.additionalImports.get(), - projectDir - ) - - def workerExecutor = workerExecutorField.get(task) - workerExecutor.processIsolation { workerSpec -> - workerSpec.forkOptions { options -> - options.jvmArgs("-XX:MaxMetaspaceSize=256m", "-Xshare:off") - } - workerSpec.classpath.from(task.routesCompilerClasspath) - }.submit(RoutesCompileWorkAction) { parameters -> - parameters.compiler.set(RoutesCompilerFactory.create(task.platform.get())) - parameters.spec.set(spec) - } - } - } -} - spotless { java { target "**/*.java" diff --git a/dd-smoke-tests/play-2.5/build.gradle b/dd-smoke-tests/play-2.5/build.gradle index f0e71773b3a..d1084044680 100644 --- a/dd-smoke-tests/play-2.5/build.gradle +++ b/dd-smoke-tests/play-2.5/build.gradle @@ -4,6 +4,7 @@ plugins { apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-routes.gradle" +apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle" testJvmConstraints { // TODO Java 17: This version of play doesn't support Java 17 diff --git a/dd-smoke-tests/play-2.6/build.gradle b/dd-smoke-tests/play-2.6/build.gradle index 2d95b942697..54272256723 100644 --- a/dd-smoke-tests/play-2.6/build.gradle +++ b/dd-smoke-tests/play-2.6/build.gradle @@ -4,6 +4,7 @@ plugins { apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-routes.gradle" +apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle" testJvmConstraints { // TODO Java 17: This version of play doesn't support Java 17 diff --git a/dd-smoke-tests/play-2.7/build.gradle b/dd-smoke-tests/play-2.7/build.gradle index 32001a18e7e..a4a6c127de4 100644 --- a/dd-smoke-tests/play-2.7/build.gradle +++ b/dd-smoke-tests/play-2.7/build.gradle @@ -4,6 +4,7 @@ plugins { apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-routes.gradle" +apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle" testJvmConstraints { // TODO Java 17: This version of play doesn't support Java 17 diff --git a/dd-smoke-tests/play-2.8-otel/build.gradle b/dd-smoke-tests/play-2.8-otel/build.gradle index 689d177c9dd..420e60e2899 100644 --- a/dd-smoke-tests/play-2.8-otel/build.gradle +++ b/dd-smoke-tests/play-2.8-otel/build.gradle @@ -4,6 +4,7 @@ plugins { apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-routes.gradle" +apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle" def playVer = "2.8.15" def scalaVer = System.getProperty("scala.version", /* default = */ "2.13") diff --git a/dd-smoke-tests/play-2.8-split-routes/build.gradle b/dd-smoke-tests/play-2.8-split-routes/build.gradle index 838c9aee693..2721c99b3e0 100644 --- a/dd-smoke-tests/play-2.8-split-routes/build.gradle +++ b/dd-smoke-tests/play-2.8-split-routes/build.gradle @@ -4,6 +4,7 @@ plugins { apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-routes.gradle" +apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle" def playVer = "2.8.15" def scalaVer = System.getProperty("scala.version", /* default = */ "2.13") diff --git a/dd-smoke-tests/play-2.8/build.gradle b/dd-smoke-tests/play-2.8/build.gradle index 3cf6e17d7f7..95cf5e8c82d 100644 --- a/dd-smoke-tests/play-2.8/build.gradle +++ b/dd-smoke-tests/play-2.8/build.gradle @@ -4,6 +4,7 @@ plugins { apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-routes.gradle" +apply from: "$rootDir/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle" def playVer = "2.8.15" def scalaVer = System.getProperty("scala.version", /* default = */ "2.13") diff --git a/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle b/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle new file mode 100644 index 00000000000..b1a74b7ef73 --- /dev/null +++ b/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle @@ -0,0 +1,58 @@ +import datadog.gradle.plugin.HostPlatform + +// Fix for JVM crashes (SIGSEGV / SIGABRT, exit 134) when the +// org.gradle.playframework `compilePlayRoutes` Worker Daemon starts up on Linux arm64. +// No-op on every other host/arch combination. +if (HostPlatform.isLinuxArm64()) { + tasks.named("compilePlayRoutes").configure { task -> + // Find the class in the hierarchy that declares the private `workerExecutor` field. + def workerExecutorField = null + def declaringClass = task.getClass() + while (declaringClass != null && workerExecutorField == null) { + try { + workerExecutorField = declaringClass.getDeclaredField("workerExecutor") + } catch (NoSuchFieldException ignored) { + declaringClass = declaringClass.getSuperclass() + } + } + if (workerExecutorField == null) { + throw new GradleException( + "compilePlayRoutes task class ${task.getClass().name} has no workerExecutor field; " + + "fix-play-linux-arm64 needs to be updated for this version of the play plugin.") + } + workerExecutorField.accessible = true + + def cl = declaringClass.getClassLoader() + def specClass = cl.loadClass('org.gradle.playframework.tools.internal.routes.DefaultRoutesCompileSpec') + def workActionClass = cl.loadClass('org.gradle.playframework.tasks.internal.RoutesCompileWorkAction') + def factoryClass = cl.loadClass('org.gradle.playframework.tools.internal.routes.RoutesCompilerFactory') + + task.actions.clear() + task.doLast { + def spec = specClass.getConstructors()[0].newInstance( + task.source.files, + task.outputDirectory.get().asFile, + task.javaProject, + task.namespaceReverseRouter.get(), + task.generateReverseRoutes.get(), + task.injectedRoutesGenerator.get(), + task.additionalImports.get(), + projectDir + ) + + def workerExecutor = workerExecutorField.get(task) + def platform = task.platform.get() + def compiler = factoryClass.getMethod('create', platform.getClass()).invoke(null, platform) + + workerExecutor.processIsolation { workerSpec -> + workerSpec.forkOptions { options -> + options.jvmArgs("-XX:MaxMetaspaceSize=256m", "-Xshare:off") + } + workerSpec.classpath.from(task.routesCompilerClasspath) + }.submit(workActionClass) { parameters -> + parameters.compiler.set(compiler) + parameters.spec.set(spec) + } + } + } +} From 4a6c5a5665c8c50c6ed9426f953099bbe2927b34 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 24 May 2026 18:44:24 -0400 Subject: [PATCH 23/24] Fix reworked. --- dd-smoke-tests/play-common/fix-play-linux-arm64.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle b/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle index b1a74b7ef73..1c3e27fabc0 100644 --- a/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle +++ b/dd-smoke-tests/play-common/fix-play-linux-arm64.gradle @@ -26,6 +26,9 @@ if (HostPlatform.isLinuxArm64()) { def specClass = cl.loadClass('org.gradle.playframework.tools.internal.routes.DefaultRoutesCompileSpec') def workActionClass = cl.loadClass('org.gradle.playframework.tasks.internal.RoutesCompileWorkAction') def factoryClass = cl.loadClass('org.gradle.playframework.tools.internal.routes.RoutesCompilerFactory') + // The `platform` value at runtime is `PlayPlatform_Decorated` (Gradle's generated subclass). + // `Class.getMethod` requires an exact parameter-type match, so look up the undecorated type. + def platformClass = cl.loadClass('org.gradle.playframework.extensions.PlayPlatform') task.actions.clear() task.doLast { @@ -42,7 +45,7 @@ if (HostPlatform.isLinuxArm64()) { def workerExecutor = workerExecutorField.get(task) def platform = task.platform.get() - def compiler = factoryClass.getMethod('create', platform.getClass()).invoke(null, platform) + def compiler = factoryClass.getMethod('create', platformClass).invoke(null, platform) workerExecutor.processIsolation { workerSpec -> workerSpec.forkOptions { options -> From f3162e465e1fe4f1c10c473dc823ec6587bc0f42 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 24 May 2026 21:30:05 -0400 Subject: [PATCH 24/24] Ignore Oracle8 arm64. --- .gitlab-ci.yml | 2 +- ...trace-java.test-jvm-constraints.gradle.kts | 11 ---------- .../environment/CommandLineHelper.java | 21 ------------------- .../datadog/environment/CommandLineTest.java | 15 ++----------- .../writer/DDAgentWriterCombinedTest.groovy | 9 -------- .../writer/DDIntakeWriterCombinedTest.groovy | 9 -------- 6 files changed, 3 insertions(+), 64 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1a6f1f94f46..be8e2de9d59 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -728,7 +728,7 @@ muzzle-dep-report: - if: $testJvm =~ $DEFAULT_TEST_JVMS when: manual allow_failure: true - - if: '$NON_DEFAULT_JVMS == "true" && $testJvm != "ibm8"' + - if: '$NON_DEFAULT_JVMS == "true" && $testJvm != "ibm8" && $testJvm != "oracle8"' when: manual allow_failure: true cache: diff --git a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts index 19ba90cd96f..41868d093d1 100644 --- a/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts +++ b/buildSrc/src/main/kotlin/dd-trace-java.test-jvm-constraints.gradle.kts @@ -89,17 +89,6 @@ private fun Test.configureTestJvm(extension: TestJvmConstraintsExtension) { listOf("-Djdk.attach.allowAttachSelf=true") ) } - - // Mitigation for SIGSEGV in Parallel Old GC on Oracle JDK 8 / linux-aarch64 - // (InstanceKlass::oop_follow_contents in PSParallelCompact). Switching to Serial GC - // removes the crashing code path entirely. See crash.md. - if (HostPlatform.isLinuxArm64()) { - conditionalJvmArgs( - JavaVersion.VERSION_1_8, - listOf("-XX:+UseSerialGC"), - testJvmSpec.testJvmProperty.map { it == "8" || it == "oracle8" }.orElse(false) - ) - } } // Jacoco plugin is not applied on every project diff --git a/components/environment/src/test/java/datadog/environment/CommandLineHelper.java b/components/environment/src/test/java/datadog/environment/CommandLineHelper.java index 28eaeb553f7..d2e17ba0150 100644 --- a/components/environment/src/test/java/datadog/environment/CommandLineHelper.java +++ b/components/environment/src/test/java/datadog/environment/CommandLineHelper.java @@ -99,27 +99,6 @@ static RunArguments of(List jvmArgs, List cmdArgs) { arguments.cmdArgs = cmdArgs; return arguments; } - - /** - * Prepends {@code -XX:+UnlockExperimentalVMOptions} when the JVM options reference an - * experimental flag on the current JVM. Required for {@code -XX:+UseG1GC} on Oracle JDK 8 - * aarch64, where G1GC is shipped as experimental. - */ - RunArguments withUnlockExperimentalVMOptionsIfNeeded() { - if (!needsUnlockExperimentalVMOptions(jvmOptions)) { - return this; - } - List updated = new ArrayList<>(jvmOptions.size() + 1); - updated.add("-XX:+UnlockExperimentalVMOptions"); - updated.addAll(jvmOptions); - return RunArguments.of(updated, cmdArgs); - } - - private static boolean needsUnlockExperimentalVMOptions(List jvmOptions) { - return JavaVirtualMachine.isOracleJDK8() - && OperatingSystem.architecture().isArm64() - && jvmOptions.contains("-XX:+UseG1GC"); - } } static class Result extends RunArguments { diff --git a/components/environment/src/test/java/datadog/environment/CommandLineTest.java b/components/environment/src/test/java/datadog/environment/CommandLineTest.java index 384bcd487e0..b1673b80a29 100644 --- a/components/environment/src/test/java/datadog/environment/CommandLineTest.java +++ b/components/environment/src/test/java/datadog/environment/CommandLineTest.java @@ -36,25 +36,17 @@ static Stream data() { of(emptyList(), emptyList()) ), arguments( - "JVM options only with G1GC", + "JVM options only", of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), emptyList()), of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), emptyList())), - arguments( - "JVM options only with ParallelGC", - of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), emptyList()), - of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), emptyList())), arguments( "Command arguments only", of(emptyList(), asList("arg1", "arg2")), of(emptyList(), asList("arg1", "arg2"))), arguments( - "Both JVM options and command arguments with G1GC", + "Both JVM options and command arguments", of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), asList("arg1", "arg2")), of(asList("-Xmx128m", "-XX:+UseG1GC", "-Dtest.property=value"), asList("arg1", "arg2"))), - arguments( - "Both JVM options and command arguments with ParallelGC", - of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), asList("arg1", "arg2")), - of(asList("-Xmx128m", "-XX:+UseParallelGC", "-Dtest.property=value"), asList("arg1", "arg2"))), arguments( "JVM options from argfile", of(asList("-Dtest.property=value", argFile("carriage-return-separated")), asList("arg1", "arg2")), @@ -81,9 +73,6 @@ void testGetVmArguments(String useCase, RunArguments arguments, RunArguments exp throws Exception { // Skip unsupported test cases skipArgFileTestOnJava8(arguments); - // Unlock experimental options when needed (e.g. UseG1GC on Oracle JDK 8 aarch64) - arguments = arguments.withUnlockExperimentalVMOptionsIfNeeded(); - expectedArguments = expectedArguments.withUnlockExperimentalVMOptionsIfNeeded(); // Run test process Result result = forkAndRunWithArgs(arguments); // Check results diff --git a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy index 2a72eaf0780..1659ab44da3 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDAgentWriterCombinedTest.groovy @@ -1,6 +1,5 @@ package datadog.trace.common.writer -import static datadog.environment.OperatingSystem.architecture import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer import static datadog.trace.api.ProtocolVersion.V0_5 import static datadog.trace.api.config.GeneralConfig.EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED @@ -8,8 +7,6 @@ import static datadog.trace.common.writer.DDAgentWriter.BUFFER_SIZE import static datadog.trace.common.writer.ddagent.Prioritization.ENSURE_TRACE import datadog.communication.ddagent.DDAgentFeaturesDiscovery -import datadog.environment.JavaVirtualMachine -import datadog.environment.OperatingSystem import datadog.communication.http.OkHttpUtils import datadog.communication.serialization.ByteBufferConsumer import datadog.communication.serialization.FlushingBuffer @@ -41,7 +38,6 @@ import java.util.concurrent.Semaphore import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger import okhttp3.HttpUrl -import spock.lang.IgnoreIf import spock.lang.Timeout import spock.util.concurrent.PollingConditions @@ -197,11 +193,6 @@ class DDAgentWriterCombinedTest extends DDCoreSpecification { agentVersion << ["v0.3/traces", "v0.4/traces", "v0.5/traces"] } - // TODO: Oracle JDK 8 on linux-aarch64 crashes in PSPromotionManager under the heavy allocation - // pressure of this test. - @IgnoreIf({ - OperatingSystem.isLinux() && architecture().isArm64() && JavaVirtualMachine.isOracleJDK8() - }) @Timeout(30) def "test default buffer size for #agentVersion"() { setup: diff --git a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy index 86784e2230e..966d4e91ecb 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/DDIntakeWriterCombinedTest.groovy @@ -1,8 +1,6 @@ package datadog.trace.common.writer import datadog.communication.http.OkHttpUtils -import datadog.environment.JavaVirtualMachine -import datadog.environment.OperatingSystem import datadog.communication.serialization.ByteBufferConsumer import datadog.communication.serialization.FlushingBuffer import datadog.communication.serialization.msgpack.MsgPackWriter @@ -26,7 +24,6 @@ import datadog.trace.core.propagation.PropagationTags import datadog.trace.core.test.DDCoreSpecification import datadog.trace.test.util.Flaky import okhttp3.HttpUrl -import spock.lang.IgnoreIf import spock.lang.Shared import spock.lang.Timeout import spock.util.concurrent.PollingConditions @@ -38,7 +35,6 @@ import java.util.concurrent.Semaphore import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger -import static datadog.environment.OperatingSystem.architecture import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer import static datadog.trace.common.writer.DDIntakeWriter.BUFFER_SIZE import static datadog.trace.common.writer.ddagent.Prioritization.ENSURE_TRACE @@ -189,11 +185,6 @@ class DDIntakeWriterCombinedTest extends DDCoreSpecification { trackType << [TrackType.CITESTCYCLE] } - // TODO: Oracle JDK 8 on linux-aarch64 crashes in PSPromotionManager under the heavy allocation - // pressure of this test. - @IgnoreIf({ - OperatingSystem.isLinux() && architecture().isArm64() && JavaVirtualMachine.isOracleJDK8() - }) @Timeout(30) def "test default buffer size for #trackType"() { setup: