Build DatadogClassLoader resource URL from agent jar URL, not OS path#11480
Build DatadogClassLoader resource URL from agent jar URL, not OS path#11480dougqh wants to merge 1 commit into
Conversation
`agentResourcePrefix` was constructed via `"jar:file:" + JarFile.getName() + "!/"`. `JarFile.getName()` returns the OS-native path. On Windows that is `C:\Datadog\dd-java-agent.jar`, producing the malformed URL `jar:file:C:\Datadog\dd-java-agent.jar!/...` — the backslashes are not valid in a URL path and the embedded `file:C:\...` is missing the leading slash before the drive letter. `new URL(...)` is permissive enough to accept the string, but `URLConnection.openStream()` then fails, so `findResource()` returns URLs that cannot be read. This breaks helper-class injection on Spring Boot 1.3.5 fat jars (and WARs) on Windows: byte-buddy's `ClassFileLocator.ForClassLoader` surfaces the failure as `IllegalStateException: Could not locate class file for <helper>` and `HelperInjector.getHelperMap` propagates it. Without the Servlet3 and Tomcat helpers no entry spans are created, so no traces reach the Agent. Use the well-formed `agentJarURL` (already built via `File.toURI().toURL()` upstream) instead. The migrated test exercises the regression cross-platform by placing the test jar in a directory whose name contains a space — `URL.toString()` percent-encodes it, `JarFile.getName()` does not — which is the same class of malformation Windows triggers. Migrate `DatadogClassLoaderTest.groovy` to Java JUnit 5 per project convention (uses reflection for the protected `getClassLoadingLock`). Fixes #6398 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eb8f7171ec
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // original Groovy test did implicitly. | ||
| private static Object classLoadingLock(ClassLoader cl, String name) throws Exception { | ||
| Method m = ClassLoader.class.getDeclaredMethod("getClassLoadingLock", String.class); | ||
| m.setAccessible(true); |
There was a problem hiding this comment.
Avoid reflective access to getClassLoadingLock
When this test runs on Java 16+ (the module's test config only opens java.base/java.net for those launchers in dd-java-agent/agent-bootstrap/build.gradle), this setAccessible(true) throws InaccessibleObjectException because java.base/java.lang is not opened. That makes DatadogClassLoaderTest fail before it exercises the lock behavior on current JDKs; use a small test-only subclass/wrapper to call the protected method or add the matching --add-opens.
Useful? React with 👍 / 👎.
🟢 Java Benchmark SLOs — All performance SLOs passed
PR vs. master resultsStartup Time
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
What Does This Do
Fix Windows-only helper-class injection failure that breaks tracing on Spring Boot 1.3.5 fat jars / WARs (and any app using
org.springframework.boot.loader.LaunchedURLClassLoader).Motivation
Fixes a regression introduced in v0.107.0
Additional Notes
DatadogClassLoaderbuildsagentResourcePrefixfromJarFile.getName()(an OS-native path). On Windows that string isC:\Datadog\dd-java-agent.jar, producing the malformed URLjar:file:C:\Datadog\dd-java-agent.jar!/...— backslashes are not valid in a URL path and the embeddedfile:C:\...is missing the leading slash before the drive letter.new URL(...)accepts the string, butURLConnection.openStream()then fails, sofindResource()returns URLs that cannot be read.This breaks helper-class injection: byte-buddy's
ClassFileLocator.ForClassLoader(used byHelperInjector) surfaces the failure asIllegalStateException: Could not locate class file for <helper>. Without the Servlet3 / Tomcat helpers no entry spans are created, so no traces reach the Agent.The fix builds the prefix from the well-formed
agentJarURL(already produced viaFile.toURI().toURL()upstream) instead of round-tripping throughJarFile.getName().Regression boundary: introduced by #3684 (commit
556da4ea35, between v0.106.0 and v0.107.0) — matches the working/broken matrix reported in the linked issue.Test plan
findResourceUsesAgentJarUrlAsPrefix) places the test jar in a directory whose name contains a space.URL.toString()percent-encodes it;JarFile.getName()does not. The pre-fix code produces a URL with the literal space; the post-fix code matches the agent-jar URL prefix exactly. Verified the test fails on pre-fix code and passes on post-fix code.:dd-java-agent:agent-bootstrap:testpasses (all 4 tests, including the 3 migrated fromDatadogClassLoaderTest.groovy).Notes
DatadogClassLoaderTest.groovy→ JUnit 5 Java per project convention. The pre-existing tests are preserved (getClassLoadingLockis reached via reflection since it'sprotectedonjava.lang.ClassLoader).Fixes #6398
🤖 Generated with Claude Code