Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f9b93ae
feat(agent,client,extension,docs,tests): add manifest-libs (flag) + l…
jbachorik Jan 7, 2026
649e625
fix(agent): retransform Thread after startup scripts for early hooks
jbachorik Jan 12, 2026
f1b2ed9
fix(agent,client,tests): probe listing after disconnect and test isol…
jbachorik Jan 13, 2026
3b7e940
Update btrace-agent/src/main/java/org/openjdk/btrace/agent/Main.java
jbachorik Jan 13, 2026
19eb31a
Update btrace-extension/src/main/java/org/openjdk/btrace/extension/ut…
jbachorik Jan 13, 2026
2346a69
Rename load(String, Object) to loadFromContext to avoid overload conf…
Copilot Jan 13, 2026
94c9e76
fix(agent): replace List.of() with Collections.emptyList() for Java 8…
Copilot Jan 13, 2026
bf663d1
feat(extension): add embedded extension support with ClassDataLoader
jbachorik Jan 15, 2026
c17340b
feat(plugin): add fat agent Gradle and Maven plugins
jbachorik Jan 16, 2026
5d295df
fix(instr): exclude JDK 25 Thread accessor methods from instrumentation
jbachorik Jan 19, 2026
5ace549
fix(security): harden security boundaries and add plugin tests
jbachorik Jan 22, 2026
679fa1d
fix(extension): make isValidClassName regex non-backtracking
jbachorik Apr 11, 2026
aeb541e
fix: address scholic-chorus review findings across agent, extension, …
jbachorik Apr 11, 2026
d932c45
fix(extension): serialize ClassDataLoader.findClass per class name
jbachorik Apr 11, 2026
afb919a
fix: address PR review feedback (race condition, regex safety, perf)
jbachorik Apr 12, 2026
b67e860
fix(build): remove stale conflict marker text from integration-tests …
jbachorik Apr 12, 2026
4d0cbeb
fix(build): update fat agent config to use btraceJar (masked JAR arch…
jbachorik Apr 12, 2026
c0171e5
fix(build): remove stale rebase artifacts from Main.java and RemoteCl…
jbachorik Apr 12, 2026
11cfc18
fix(build): remove stale rebase artifact from BTraceFunctionalTests.java
jbachorik Apr 12, 2026
d992a92
fix(test): use distinct port for ManifestLibsTests to avoid contention
jbachorik Apr 12, 2026
85203a7
fix(test): pass btrace.port to spawned BTrace client process
jbachorik Apr 12, 2026
df437cd
docs: update all documentation for masked JAR architecture
jbachorik Apr 12, 2026
3dcea1b
Address PR review feedback
jbachorik Apr 17, 2026
6295796
fix(test): resolve duplicate -p flag after rebase onto develop
jbachorik Apr 17, 2026
84576bf
fix: address review findings in PR #791
jbachorik Apr 21, 2026
21c5945
docs: document ordering and null-classloader contracts
jbachorik Apr 21, 2026
a1dab3a
Merge branch 'develop' into jb/configurations
jbachorik Apr 22, 2026
649d808
address: respond to Copilot review comments on PR #791
jbachorik Apr 23, 2026
af8c8df
feat(core): add @ExternalType annotation for app-type adapter generation
jbachorik Apr 24, 2026
f33dd57
feat(ext-processor): scaffold module for @ExternalType annotation pro…
jbachorik Apr 24, 2026
58801cc
test(ext-processor): add in-memory compile test harness
jbachorik Apr 24, 2026
de38326
feat(ext-processor): detect @ExternalType interfaces and emit stub ad…
jbachorik Apr 24, 2026
42393c4
feat(ext-processor): extract AdapterSpec + MethodSpec and emit method…
jbachorik Apr 24, 2026
60d96cb
feat(ext-processor): emit lazy MethodHandle dispatchers for virtual m…
jbachorik Apr 24, 2026
647d61c
test(ext-processor): verify static dispatcher uses findStatic + TCCL
jbachorik Apr 24, 2026
af37d26
test(ext-processor): end-to-end smoke test for generated adapter invo…
jbachorik Apr 24, 2026
286543a
feat(ext-processor): emit compile errors for invalid @ExternalType ta…
jbachorik Apr 24, 2026
96ac969
feat(ext-plugin): auto-register @ExternalType annotation processor on…
jbachorik Apr 24, 2026
178745c
feat(example): migrate Spark onJobStart adapter to @ExternalType
jbachorik Apr 24, 2026
0b40d59
docs: document @ExternalType adapter generator
jbachorik Apr 24, 2026
6ba2212
fix(ext-processor): erase generic types for MethodType literal; use l…
jbachorik Apr 24, 2026
922fc30
feat(ext): integration test, TCCL null-guard, and code cleanup for @E…
jbachorik May 1, 2026
04a682b
chore: ignore .worktrees/ directory
jbachorik May 1, 2026
f61a9d1
Use single-source repo layout for extensions
jbachorik May 1, 2026
dfb8fd0
Javadoc fix
jbachorik May 1, 2026
638722f
fix: address review feedback - formatting, brittle index, throws decl…
Copilot May 1, 2026
3d2b213
fix: doc link casing, vm.detach() resource leak, test file formatting
Copilot May 1, 2026
dff8367
refactor: fix fd leak, remove dead code, and eliminate redundant oper…
jbachorik May 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ gradle.properties
gradle-wrapper.properties

/.java.versions
compile.log
.worktrees/
194 changes: 135 additions & 59 deletions .muse/advisor.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,144 @@
# BTrace Project Advisor

## Repository: btraceio/btrace

### Branch model

- **`develop`** is the sole integration branch — ALL pull requests must target `develop`, never `master`.
---
name: btrace-advisor
role: repo_advisor
scope: [btraceio/btrace]
confidence: high
concertato_only: true
watched_paths:
- AGENTS.md
- CONTRIBUTING.md
- README.md
- build.gradle
- settings.gradle
- .github/workflows/continuous.yml
- .github/workflows/v2-protocol-tests.yml
- .github/workflows/release.yml
- .github/workflows/codeql-analysis.yml
---

# BTrace Repo Advisor

Operational facts for `btraceio/btrace`. No reviewer opinions — only repo-specific truths for build, test, CI, and layout.

## Branch Model

- `develop` is the sole integration branch — ALL pull requests target `develop`.
- `master` does not exist on the remote.
- Release tags are cut from `develop` after a stabilization window.
- Branch from `develop` for features/fixes (see `CONTRIBUTING.md`).

### Build commands

```bash
# Full build with dist packages
./gradlew :btrace-dist:build

# Module-specific build (faster)
./gradlew :<module>:build -x test

# All tests
./gradlew test

# Instrumentation tests only (fastest for instr changes)
./gradlew :btrace-instr:test
## Build System

# Regenerate golden files after intentional bytecode changes
./gradlew :btrace-instr:test -PupdateTestData
- Build tool: Gradle with the bundled wrapper (`./gradlew`). Pinned Gradle version downloaded on first run.
- Root toolchain: JDK 11 compiles the build; `btrace-core` and `btrace-runtime` sources target Java 8.
- Included build: `btrace-gradle-plugin` is consumed via `pluginManagement { includeBuild(...) }`.
- Subprojects: auto-discovered by root `build.gradle`/`settings.gradle` matching `btrace-*` directories that contain `build.gradle`. Skipped: `btrace-gradle-plugin` (handled above), and legacy `btrace-services`, `btrace-services-api`, `btrace-statsd`.
- Dependency versions live in `settings.gradle` `dependencyResolutionManagement.versionCatalogs.libs`: ASM 9.9.1, JUnit 5.11.4, SLF4J 1.7.36, JCTools 4.0.6, JMH 1.37, testcontainers 2.0.4.
- Do **not** consume Gradle task output directly — write logs to a file, filter with `grep`, then read the filtered file (AGENTS.md directive).

# Integration tests (requires Docker + full dist build first)
./gradlew :btrace-dist:build
./gradlew :integration-tests:test -Pintegration
### Commands

# Format check / auto-format (Google Java Format via Spotless)
./gradlew spotlessCheck
./gradlew spotlessApply
```bash
./gradlew build # compile + unit tests for all modules
./gradlew :btrace-dist:build # build distribution (ZIP/TGZ/RPM/DEB + exploded layout)
./gradlew :btrace-dist:btraceJar # just rebuild the masked jar
./gradlew :<module>:build -x test # faster module build
./gradlew :btrace-instr:test # instrumentation-only tests
./gradlew :btrace-instr:test -PupdateTestData # regenerate instrumentor goldens
./gradlew :integration-tests:test -Pintegration # requires built dist first
./gradlew spotlessCheck | spotlessApply # Google Java Format (Spotless)
./gradlew jacocoTestReport # coverage (CI uploads to Codecov)
```

### Module layout

| Module | Purpose |
### Environment variables

- `JAVA_HOME` — build JDK (typically 21 locally; CI build row is 11).
- `TEST_JAVA_HOME` — JDK used to **run** tests; CI exports this per matrix row. For integration tests you usually want `TEST_JAVA_HOME=$JAVA_11_HOME`. Locally, setting it is the way to exercise Java 8 / 17 / 21 / 25 / 26-ea runtime paths.
- `BTRACE_TEST_DEBUG=true` — verbose integration-test output.
- `BTRACE_HOME` — optional; used when running an exploded dist (e.g. `btrace-dist/build/resources/main/v<version>/`).
- `BTRACE_PERMS` / `-Dbtrace.permissions=<path>` — privileged-extensions policy for integration tests (see `CONTRIBUTING.md`).
- `GRADLE_USER_HOME=$(pwd)/.gradle-user` — recommended in restricted/CI environments to avoid permission issues with the shared cache.
- `JAVA_TOOL_OPTIONS="-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false"` — force IPv4 when wildcard-IP detection fails in Gradle.
- Sonatype publishing: `SONATYPE_USER` / `SONATYPE_USERNAME`, `SONATYPE_PASSWORD`, `GPG_SIGNING_KEY`, `GPG_SIGNING_PWD` (release workflow only).

## Test Infrastructure

- Framework: **JUnit 5 (Jupiter)** for both unit and integration tests.
- Unit tests: under each module's `src/test/java`, naming convention `*Test`.
- Integration tests: `integration-tests/src/test/java` (scripts under `integration-tests/src/test/btrace`) — spawn real JVMs, exercise agent + extensions, require Docker (`DOCKER_HOST=unix:///var/run/docker.sock`) and `btrace-dist/build/resources/main/v<version>/libs/btrace.jar` on disk.
- Golden instrumentor fixtures: `btrace-instr/src/test/resources/instrumentorTestData/dynamic/` — regenerate with `-PupdateTestData` after any intentional bytecode change; commit the updated goldens.
- V2 protocol tests: `btrace-core` test class globs `org.openjdk.btrace.core.comm.v2.*`, `Protocol*`, `WireProtocol*`. Dedicated workflow runs on label `test:v2-protocol`, weekly schedule, or manual dispatch.
- Running a single test: `./gradlew :btrace-instr:test --tests "org.openjdk.btrace.runtime.ExtensionIndyShimIndexTest.resolvesNoopShimFromIndex"`.
- Per-module aliases from `CONTRIBUTING.md`: `:btrace-runtime:test`, `:btrace-extension:test`, `:btrace-compiler:test`, `:btrace-instr:test`.
- CI JDK matrix (build: JDK 11): tests run on `8.0.482-tem, 11.0.30-tem, 17.0.18-tem, 21.0.10-tem, 25.0.2-tem, 26.ea.35-open` — changes must compile and pass across all of these.

## Distribution — Masked JAR

- Single artifact: `btrace.jar` with bootstrap classes as `.class` and mode-scoped classes as `.classdata` under `META-INF/btrace/{agent,client,shared}/`.
- Loader: `org.openjdk.btrace.boot.Loader` is `Main-Class`, `Premain-Class`, and `Agent-Class`. `MaskedClassLoader` resolves `.classdata`.
- Every new class **must** be categorized: agent-only, client-only, or shared. Categorization is wired into `btrace-dist/build.gradle`'s `prepareAgentClassdata` / `prepareClientClassdata` / `prepareSharedClassdata` include patterns.
- Rebuild masked jar after any restructuring: `./gradlew clean :btrace-dist:btraceJar`.
- Inspect: `unzip -l btrace.jar | grep -E '(\.class|\.classdata)'`; `unzip -p btrace.jar META-INF/MANIFEST.MF`.
- Build-order dependency: `allClassesShadow` must complete before `prepare*Classdata` tasks run; those must complete before `btraceJar` assembles.

## Known Sharp Edges

- **Javadoc API version trap**: `btrace-runtime/src/main/java/org/openjdk/btrace/runtime/auxiliary/` is compiled at Java 8 source/target. Javadoc linking to JDK 15+ API (e.g. hidden-class lookups) breaks `:btrace-runtime:javadoc` with `reference not found`. Keep javadoc references on pre-9 API or use prose.
- **Bootstrap classloader constraints**: `btrace-boot.jar` lives on the bootstrap classpath. Any class referenced from an `INVOKEDYNAMIC` bootstrap method (e.g. `IndyDispatcher`) must be bootstrap-loadable. Pulling in application-classloader-only types breaks probe dispatch.
- **Hidden-class vs `defineClass` paths**: probe script classes are defined in the bootstrap CL via `Unsafe.defineClass` with `mustBeBootstrap=true` when `isTransforming()`. JDK 15+ has a separate hidden-class codepath — multi-version runtime (`src/main/java9/`, `src/main/java11/`, `src/main/java15/`) keeps these isolated; compile each at its release level.
- **Verifier contract**: probe handler methods are always `public static void`. `MethodHandles.publicLookup().findStatic(...)` is sufficient — do not switch to `privateLookupIn` "just to be safe," it breaks bootstrap loader expectations.
- **FQN rule**: never inline fully qualified names in source. Always import and use simple type names (AGENTS.md hard rule).
- **Masked-JAR class invisibility**: `ClassNotFoundException` on `.classdata` means the class is either missing from the correct mode section or was relocated but not registered. `shared/` is required whenever agent ↔ client serialize the same type (comm protocol, annotations, ASM core).
- **`BTraceRuntimeImpl_8` diverges** from 9/11 impls on the `defineClass` path — Java 8 CI row is not redundant; always verify against it via `TEST_JAVA_HOME=$JAVA_8_HOME` locally before merging runtime changes.
- **Spotless import order**: `java`, `javax`, `org.openjdk.btrace`, everything else, static `org.openjdk.btrace`, remaining static. Reformat with `./gradlew spotlessApply` if `spotlessCheck` fails.
- **License header**: Spotless injects `/* (C) $YEAR */` on every Java file; do not hand-write headers.

## Known Recurring CI Failure Modes

- **`:initializeSonatypeStagingRepository FAILED — Failed to find staging profile for package group`** on the `publish` job of BTrace CI/CD when `develop` merges. Tied to the OSSRH → Central Portal migration (`nexusPublishing` in root `build.gradle` uses `https://ossrh-staging-api.central.sonatype.com/`). Publish is guarded by `hasSonatypeCredentials` + non-snapshot version; failures typically reflect missing/rotated Central Portal user-token credentials or an unregistered `io.github.*` package group on the new portal.
- **`btrace-runtime:javadoc FAILED — reference not found`** — see Javadoc API version trap above. Caught by the build job (not the test matrix).
- **CodeQL `configuration error`** — CodeQL workflow trips on feature branches with unusual Java toolchain setups; typically a Java setup/classpath mismatch in `actions/codeql-action@v*`, not a real finding.
- **Integration test branch-scoped failures** (e.g. `ManifestLibsTests > Dynamic attach with manifest-libs enabled`) — matrix-wide failure usually means the feature branch changed something in extension-loading or masked-jar layout that works for default attach but not dynamic attach. Not a flaky test — debug the change, don't retry.

## PR and CI Rules

- **Commit style**: Conventional Commits (`feat(core):`, `fix(instr):`, `refactor(runtime):`, `test:`, `chore:`). Scope matches module short name.
- **OCA required**: PRs are only accepted from signers of the Oracle Contributor Agreement.
- **PR checklist** (from AGENTS.md + CONTRIBUTING.md):
1. Target branch is `develop` (never `master`).
2. `./gradlew spotlessCheck` clean.
3. Unit tests updated/added.
4. `-PupdateTestData` goldens regenerated **and committed** if instrumentation changed.
5. Integration tests pass locally if agent/dist behavior changed.
6. For behavior changes, include before/after notes or logs.
7. No unrelated changes in the diff.
- **CI workflows**:
- `BTrace CI/CD` (`continuous.yml`) — build + matrix test + (on `develop`) publish + cleanup. Triggered on push/PR against `develop` and `workflow_dispatch`.
- `V2 Protocol Tests` (`v2-protocol-tests.yml`) — opt-in via PR label `test:v2-protocol`, weekly on Sundays 02:00 UTC, or manual. Includes unit, negotiation, edge-case, JMH (label `[benchmark]` or manual), and V1↔V2 compatibility matrix.
- `CodeQL` (`codeql-analysis.yml`) — static analysis on push/PR.
- `release.yml` — full release pipeline (manual dispatch).
- `update-jdk-versions.yml` — periodic JDK matrix refresh.
- `stale.yml` — issue/PR staleness sweeper.
- **Optional labels** with CI meaning: `test:v2-protocol` (run the V2 suite), `[benchmark]` in commit message (run JMH quick benchmarks).

## File Layout

| Path | Purpose |
|---|---|
| `btrace-core` | Annotations, wire protocol, shared types — must stay Java 8 compatible |
| `btrace-compiler` | Script compilation + safety verification (`Verifier.java`) |
| `btrace-instr` | ASM-based bytecode instrumentation; probe factory; `HandlerRepositoryImpl` |
| `btrace-runtime` | Multi-version runtime impls (base/java9/java11/java15); `IndyDispatcher` |
| `btrace-agent` | Java agent entry point; `RemoteClient`, `FileClient` |
| `btrace-client` | CLI client tool |
| `btrace-dist` | Distribution packaging |
| `integration-tests` | End-to-end Docker-based tests |
| `benchmarks` | JMH benchmarks |

### Key architectural constraints

- `btrace-core` and `btrace-runtime` (src/main/java/) must compile at Java 8 source/target level.
- Multi-version runtime jars: `src/main/java9/`, `src/main/java11/`, `src/main/java15/` — each compiled at its respective release level.
- `btrace-boot.jar` is on the bootstrap classpath; classes in `btrace-runtime` that are referenced from INVOKEDYNAMIC bootstrap methods must be bootstrap-loadable.
- All probe script classes are defined in the bootstrap CL (via `Unsafe.defineClass` with `mustBeBootstrap=true` when `isTransforming()`).
- BTrace verifier enforces that probe handler methods are `public static void` — `publicLookup().findStatic()` is therefore sufficient.
- Golden files for instrumentation tests live in `btrace-instr/src/test/resources/instrumentorTestData/dynamic/`. Run with `-PupdateTestData` to regenerate after intentional bytecode changes.

### PR checklist

Before opening a PR, verify:
1. Branch targets **`develop`** (never `master`)
2. `./gradlew spotlessApply` applied
3. `./gradlew :btrace-instr:test` passes
4. Golden files regenerated if instrumented bytecode changed (`-PupdateTestData`)
5. If touching runtime multi-version code: test on JDK 11 and JDK 17+
| `btrace-core` | Annotations, wire protocol (v1 + v2), shared types — Java 8 compatible. |
| `btrace-compiler` | Script compilation + safety verification (`Verifier`). |
| `btrace-instr` | ASM-based bytecode instrumentation; probe factory; `HandlerRepositoryImpl`; golden-file tests. |
| `btrace-runtime` | Multi-version runtime impls (base, `java9/`, `java11/`, `java15/`); `IndyDispatcher`; `BTraceRuntimeImpl_*`. Must stay loadable from the bootstrap classloader. |
| `btrace-agent` | Java agent entry point; `RemoteClient`, `FileClient`; JFR hooks. |
| `btrace-boot` | Bootstrap classes (visible to JVM), including `Loader`, `MaskedClassLoader`, `MaskedJarUtils`. |
| `btrace-client` | CLI client — attach, send script, stream output. |
| `btrace-compiler` | Scripts → bytecode. |
| `btrace-dist` | Distribution packaging (masked jar, RPM/DEB/ZIP/TGZ). Hosts `prepareAgentClassdata` / `prepareClientClassdata` / `prepareSharedClassdata` / `btraceJar`. |
| `btrace-extension` / `btrace-extensions/*` | Extension API + bundled implementations (`btrace-metrics`, `btrace-statsd`, `btrace-utils`) and examples. Explicit includes in `settings.gradle`. |
| `btrace-gradle-plugin` | In-repo Gradle plugin for extension authorship — consumed via `includeBuild` in `pluginManagement`, not as a subproject. |
| `integration-tests` | Docker-based end-to-end tests. |
| `benchmarks/agent-benchmark`, `benchmarks/runtime-benchmarks` | JMH benchmarks. |
| `docs/` | User docs (tutorials, oneliner guide, extension dev guide). |
| `btrace-instr/src/test/resources/instrumentorTestData/dynamic/` | Instrumentor golden files — regenerate via `-PupdateTestData`. |
| `.github/workflows/` | CI config; `README.md` in the same directory documents the workflows. |
| `.muse/advisor.md` | This file. |
Loading
Loading