Skip to content

Avoid final field mutations in JUnit 5, Weaver and Karate instrumentations#11625

Draft
ManuelPalenzuelaDD wants to merge 1 commit into
masterfrom
daniel.mohedano/avoid-final-fields-modifications
Draft

Avoid final field mutations in JUnit 5, Weaver and Karate instrumentations#11625
ManuelPalenzuelaDD wants to merge 1 commit into
masterfrom
daniel.mohedano/avoid-final-fields-modifications

Conversation

@ManuelPalenzuelaDD

Copy link
Copy Markdown

What Does This Do

Removes final-field mutation from the JUnit 5, Weaver and Karate CI Visibility instrumentations and from UnsafeUtils.tryShallowClone, so test retries / EFD / quarantine / attempt-to-fix keep working when JEP 500 flips --illegal-final-field-mutation to deny (warns in JDK 26, denied by default later).

Per mutation site:

  • JUnit 5NodeTestTask.testDescriptor / NodeTestTask.node (mutated by TestTaskHandle on retries) and AbstractTestDescriptor.uniqueId (mutated by TestDescriptorHandle to give each retry a distinct ID): the final modifier is now stripped from these specific fields at class load via ByteBuddy ModifierAdjustment type advice. The existing MethodHandle setters are unchanged — JEP 500 only forbids mutating fields that are final at runtime, and the modifier is removed before any instance of the class exists, so the JVM never relies on these fields being final. AbstractTestDescriptor.uniqueId is covered by a new JUnit5TestDescriptorInstrumentation since it lives in a different type than the one JUnit5ExecutionInstrumentation matches.
  • WeaverSbtTask.queue is no longer overwritten after construction. The advice now intercepts the constructor and replaces the queue argument (@Advice.Argument(readOnly = false)) before it is assigned to the final field, so no field mutation happens at all. The queue is constructor parameter 5 with a stable signature across disney 0.8.4 → typelevel main; the two advices (LinkedBlockingQueue vs ConcurrentLinkedQueue) select via the argument type and only one matches per weaver version.
  • KarateScenarioRuntime.result (overwritten by KarateUtils.setResult after retries so the final result is reported): same final-stripping type advice as JUnit 5.
  • UnsafeUtils.tryShallowClone — field copying switched from Field.setAccessible/Field.set (forbidden by JEP 500 for final fields) to Unsafe field offsets (objectFieldOffset + put*), which JEP 500 does not cover. The clone target is a fresh unpublished instance from Unsafe.allocateInstance, so the offset writes are safe. This keeps cloning all fields (including finals) of arbitrary test descriptor classes, which the JUnit 5 retry path depends on.

Motivation

JEP 500 (integrity by default) makes final-field mutation via core reflection and MethodHandles.Lookup.unreflectSetter illegal: JDK 26 warns, and a future release flips the default to deny, at which point these instrumentations break (IllegalAccessException). Verified with the released 1.63.0 agent under --illegal-final-field-mutation=deny: agent install fails before any test runs.

Part of SDTEST-3576.

Additional Notes

  • Unsafe memory access is itself deprecated for removal (JEP 498), so the UnsafeUtils change is a stopgap that buys time on the JEP 500 timeline; eliminating Unsafe.allocateInstance-based cloning entirely requires a per-descriptor-class copy-constructor approach and is left for a follow-up.
  • The JUnit console standalone runner (shaded picocli) itself mutates final fields and crashes under deny before any test executes — independent of the tracer.

Contributor Checklist

Testing

  • :internal-api:test --tests UnsafeUtilsTest
  • :dd-java-agent:instrumentation:karate-1.0:test ✅ (10/10, includes flaky retries / EFD / quarantine / attempt-to-fix cases)
  • :dd-java-agent:instrumentation:weaver-0.9:test, :weaver084Test, :latestDepTest ✅ (29/29 — covers both queue types and latest weaver)
  • :dd-java-agent:instrumentation:junit:junit-5:junit-5.3:test fails identically on my machine on clean master (62/63 JSON-mismatch failures, pre-existing local toolchain issue) — deferring to CI for this module.
  • forbiddenApis + spotless clean on all touched modules.

@ManuelPalenzuelaDD ManuelPalenzuelaDD added tag: no release notes Changes to exclude from release notes type: refactoring comp: ci visibility Continuous Integration Visibility tag: ai generated Largely based on code generated by an AI or LLM labels Jun 11, 2026
@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 43 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-java | muzzle: [7/8]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-java | test_inst: [11, 2/8]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-java | test_inst: [11, 4/8]   View in Datadog   GitLab

View all 43 failed jobs.

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: de958ad | Docs | Datadog PR Page | Give us feedback!

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - sbt-scalatest

Job Status: success

Scenario Overhead (%)
agent 54.67
agentEvpProxy 55.15

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - nebula-release-plugin

Job Status: success

Scenario Overhead (%)
agent 38.12
agentless 37.61
agentlessCodeCoverage 44.84
agentlessLineCoverage 76.25

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - pass4s

Job Status: success

Scenario Overhead (%)
agent 5.48
agentless 7.87
agentlessCodeCoverage 18.78

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - netflix-zuul

Job Status: failed

Scenario Overhead (%)
agent 22.16
agentless 22.35
agentlessCodeCoverage 26.68
agentlessLineCoverage 26.77

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - sonar-kotlin

Job Status: success

Scenario Overhead (%)
agent 12.78
agentless 11.68
agentlessCodeCoverage 15.40
agentlessLineCoverage 18.61

@dd-octo-sts

dd-octo-sts Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 14.00 s 14.02 s [-0.9%; +0.6%] (no difference)
startup:insecure-bank:tracing:Agent 12.85 s 13.04 s [-2.1%; -0.9%] (maybe better)
startup:petclinic:appsec:Agent 17.41 s 17.02 s [+1.4%; +3.3%] (significantly worse)
startup:petclinic:iast:Agent 17.46 s 17.55 s [-1.3%; +0.2%] (no difference)
startup:petclinic:profiling:Agent 16.75 s 17.43 s [-8.4%; +0.6%] (no difference)
startup:petclinic:sca:Agent 17.37 s 17.16 s [+0.5%; +2.0%] (maybe worse)
startup:petclinic:tracing:Agent 16.50 s 16.70 s [-2.2%; -0.2%] (maybe better)

Commit: de958ad8 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - reactive-streams-jvm

Job Status: failed

Scenario Overhead (%)
agent 5.46
agentless 5.36
agentlessCodeCoverage 6.05
agentlessLineCoverage 5.70

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - spring_boot

Job Status: success

Scenario Overhead (%)
agent 16.17
agentless 9.93
agentlessCodeCoverage 13.37
agentlessLineCoverage 31.92

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Test Environment - sonar-java

Job Status: success

Scenario Overhead (%)
agent 25.16
agentless 25.08
agentlessCodeCoverage 87.01
agentlessLineCoverage 137.81

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: ci visibility Continuous Integration Visibility tag: ai generated Largely based on code generated by an AI or LLM tag: no release notes Changes to exclude from release notes type: refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant