This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is the New Relic Java Agent, a bytecode instrumentation agent that monitors Java applications at runtime. The agent attaches via the -javaagent JVM flag, uses ASM (version 9.9.1) for bytecode manipulation, and employs a "weaver" pattern to insert monitoring code into target classes as they are loaded by the JVM classloader.
The agent captures transactions, traces, metrics, errors, and logs from 440+ supported frameworks and libraries, sending telemetry data to the New Relic platform.
The product optimizes for:
- safety and stability above all else (should never crash the JVM being monitored)
- minimal impact on CPU and memory resources of the JVM being monitored
- backwards compatibility targeting the Java 8 runtime
- collection of application profiling data that is useful and accurate
- clarity over cleverness
- accessible object-oriented design
Avoid over-engineering. If a simpler solution exists, use it.
These rules are non-negotiable:
- Java 8 language level for all production code (no newer language features)
- Do NOT use lambda expressions in weaver instrumentation modules — the weaver's bytecode rewriting cannot reliably transform lambdas due to
invokedynamicbootstrap methods and classloader isolation; use anonymous classes instead - Do NOT change public APIs without explicit instructions
- Do NOT change weaver code without explicit instructions
- Preserve backward compatibility for all shared components
- Flag major architectural changes before implementing — don't just do it
- Instrumentation modules must be self-contained — dependencies must be shaded
- New dependencies require shading and licensing — only add if they provide significant value and always ask for permission first
- Gradle for build and dependency management
- JUnit + Mockito for tests
- ASM 9.9.1 for bytecode manipulation
- Caffeine for high-performance caching
- Apache
HttpClientfor data transport to the New Relic backend - Shadow Gradle plugin for relocating packages of project dependencies
- Spotbugs for static code analysis
- Jacoco for code coverage
| Entry Point | Path |
|---|---|
| Agent bootstrap | newrelic-agent/src/main/java/com/newrelic/bootstrap/BootstrapAgent.java |
| Configuration | newrelic-agent/src/main/java/com/newrelic/agent/config/AgentConfigImpl.java |
| Service registry | newrelic-agent/src/main/java/com/newrelic/agent/service/ServiceManagerImpl.java |
| Weave engine | newrelic-weaver/src/main/java/com/newrelic/weave/ClassWeave.java |
| Weave manifest cache | gradle/script/cache_weave_attributes.gradle.kts |
| Code style definition | dev-tools/code-style/java-agent-code-style.xml |
The agent uses Java's Instrumentation API (JSR 163) with two entry points in BootstrapAgent:
premain(String agentArgs, Instrumentation inst) ← normal startup via -javaagent
agentmain(String agentArgs, Instrumentation inst) ← dynamic attach
| Module | Purpose |
|---|---|
newrelic-agent |
Main agent implementation; ServiceManager, configuration, harvest cycle, data transport. Built as a shadow JAR with all dependencies relocated. |
newrelic-weaver |
Bytecode weaving engine using ASM. Matches weave classes to target classes and applies transformations at class-load time. |
newrelic-weaver-api |
Annotations for authoring weave classes (@Weave, @NewField, @WeaveWithAnnotation). |
newrelic-api |
Public API for custom instrumentation (@Trace, NewRelic.getAgent(), custom events/metrics). Ships with no-op implementations. |
agent-bridge |
Runtime bridge between instrumentation modules and agent core. Provides AgentBridge static facade with volatile references swapped in when agent loads. |
agent-bridge-datastore |
Datastore-specific bridge interfaces (connection URL parsing, vendor detection, instance metrics). |
agent-interfaces |
Internal agent interfaces shared across modules. |
agent-model |
Shared data models (metric names, error data, custom insight events). |
infinite-tracing |
Infinite Tracing via gRPC streaming to trace observer. |
443+ modules, each targeting a specific framework/version (e.g., spring-webmvc-6.0.0, kafka-clients-3.6.0). Each module contains:
- Weave classes (
@Weave) — Code injected into target classes - Utility classes — Helpers available to woven code
- SkipIfPresent classes — Conditions for when the module should not apply
Additional modules: Scala support (newrelic-scala-api, newrelic-scala3-api, Cats/ZIO/Monix integrations), build infrastructure (buildSrc, instrumentation-build), and test utilities (functional_test, instrumentation-test).
- Classloader isolation — Agent code on bootstrap and
JVMAgentClassLoaderclassloaders, instrumentation in separate classloaders.agent-bridgeclasses are visible at runtime to instrumentation but follow a different compile-time dependency path. - Manifest-based weave attributes — Cached in JAR manifests to avoid scanning every class (see
cache_weave_attributes.gradle.kts) - Service lifecycle —
ServiceManager/ServiceFactorymanage all agent services - Configuration-driven — Extensive YAML-based configuration for selective features
- Format code using
./gradlew googleJavaFormat(verify with./gradlew verifyGoogleJavaFormat) - Use descriptive names; avoid acronyms where possible
- Comments only when intent is non-obvious
- No dead code or commented-out blocks in commits
- Error handling must be explicit — no silent catches
- Error messages must include what happened AND, if possible, what to do next
- Wide version compatibility — instrumentation code may look overcomplicated for compatibility reasons; read all comments before changing
- Don't
cleanunnecessarily — The shadow JAR build fornewrelic-agentis slow. Only usecleanwhen switching branches or fixing stale class issues. For iterative development,./gradlew :module:testwithoutcleanis much faster. - Instrumentation tests need the agent JAR — Functional tests require
newrelic-agent/build/newrelicJar/newrelic.jarto exist. Build it first with./gradlew jarif missing. - Module-scoped tasks — Always scope Gradle tasks to the module you're working on (e.g.,
./gradlew :newrelic-agent:test,./gradlew :instrumentation:spring-webmvc-6.0.0:test) rather than running repo-wide. - Java version for newer modules — If an instrumentation module targets Java 11+/17+, you must pass
-Ptest11or-Ptest17to gradle or the instrumentation won't apply and tests will fail even though they appear to run. - Docker for Testcontainers — Some instrumentation tests require Docker. If tests fail with connection errors, check Docker is running.
Before considering any task complete:
- Run
./gradlew :module:verifyGoogleJavaFormaton modified modules - Run
./gradlew :module:googleJavaFormatto fix formatting if needed - Run relevant tests for modified logic
Testing rules:
- Unit tests for all reusable logic
- Empty state, null state, and error state must all be handled
- Feature-specific logic that won't be reused → co-locate with the feature
- Do not create a new abstraction for a one-off use case
- Prefer editing an existing component over creating a near-duplicate
JDK 8 is required (JAVA_HOME must point to JDK 8). Configure JDK paths in ~/.gradle/gradle.properties:
jdk8=/path/to/jdk8
jdk17=/path/to/jdk17
Verify environment: ./gradlew --version (should show JVM 1.8.x)
- Build agent jar only:
./gradlew clean jar --parallel - Build agent with all checks:
./gradlew clean build --parallel
Artifacts:
- Agent:
newrelic-agent/build/newrelicJar/newrelic.jar - API:
newrelic-api/build/libs/newrelic-api-*.jar
- Run Spotbugs:
./gradlew :module:spotbugsMain
- All unit tests:
./gradlew -PnoInstrumentation test --continue --parallel - Single module:
./gradlew -PnoInstrumentation :newrelic-weaver:test --parallel - Single test:
./gradlew -PnoInstrumentation :newrelic-weaver:test --tests "com.newrelic.weave.LineNumberWeaveTest.testRemoveWeaveLineNumbers" --parallel - With specific JDK: add
-Ptest17 - Include Scala: add
-PincludeScala
Require the agent JAR to be built first (./gradlew jar).
- All:
./gradlew functional_test:test --continue --parallel - Single:
./gradlew functional_test:test --tests test.newrelic.test.agent.AgentTest --parallel
- Single module:
./gradlew :instrumentation:akka-http-core-10.0.11:test --parallel - Single test:
./gradlew :instrumentation:vertx-web-3.2.0:test --tests com.nr.vertx.instrumentation.RoutingTest --parallel - Scala module:
./gradlew -PincludeScala :instrumentation:sttp-2.13_2.2.3:test --parallel - Java 17+ module:
./gradlew -Ptest17 :instrumentation:module-name:test --parallel