Skip to content

Conversation

@jbachorik
Copy link
Collaborator

@jbachorik jbachorik commented Jan 13, 2026

What This Enables

Trace application-specific classes without polluting application classpaths.

Previously, tracing classes loaded by the application classloader required injecting BTrace dependencies via libs= or profiles=, causing conflicts and classloading issues. This PR introduces provided-style extensions - extensions that access application classes through reflection at runtime, keeping BTrace completely isolated.

Key Capabilities

  • Application class tracing without classpath injection - Access any class loaded by the application without adding jars to its classloader
  • Runtime class discovery - Extensions use ClassLoadingUtil to load classes from the application's context at trace time
  • Safe method handles - MethodHandleCache provides efficient, cached reflective access to application methods
  • Declarative library management - New manifest-driven approach replaces error-prone libs= parameter

This pattern works for any framework or library: Spark, Hadoop, Kafka, Spring, Hibernate, or your own application classes.

Architecture Documentation

Document Description
Provided-Style Extensions Core pattern: API on bootstrap, impl via TCCL, runtime linking
Agent Manifest-Libs Manifest-driven library loading design
Migration Guide Migrating from deprecated libs/profiles
Extension Development Guide How to build provided-style extensions
Extension Manifest Format MANIFEST.MF attribute specification

Example Extensions

Breaking Changes

  • libs= and profiles= deprecated (removal planned N+2)
  • Permission annotations removed (were non-functional)

🤖 Generated with Claude Code

@jbachorik jbachorik added the AI AI-generated code label Jan 13, 2026
Copy link

@reviewabot reviewabot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the pull request diff is too large to be displayed directly on GitHub. Here are some general recommendations for handling large pull requests:

  1. Break Down the PR: Try to break down the pull request into smaller, more manageable chunks. This makes it easier to review and ensures that each part can be thoroughly checked.

  2. Review Locally: Clone the repository and check out the branch locally. This allows you to review the changes using your preferred tools and environment.

  3. Focus on Key Areas: Identify and focus on the key areas of the code that are most critical or have the highest impact. This can help prioritize the review process.

  4. Automated Tools: Use automated code review tools and linters to catch common issues and enforce coding standards.

  5. Collaborate with the Team: If possible, involve multiple reviewers to share the workload and get different perspectives on the changes.

If you can provide a smaller subset of the changes or specific files that need review, I'd be happy to help with a more detailed review.

@jbachorik jbachorik changed the title fix(agent,client,tests): probe listing after disconnect and test isolation feat: manifest-libs, provided-style extensions, permission removal, and fixes Jan 13, 2026
@jbachorik jbachorik changed the title feat: manifest-libs, provided-style extensions, permission removal, and fixes feat: provided-style extensions and manifest-libs Jan 13, 2026
jbachorik and others added 3 commits January 13, 2026 17:29
…ibs deprecation; provided-style helpers; examples; tests\n\n- agent: manifest-driven libs (flagged), centralized classpath append with dedup + diagnostics; deprecate libs (debug log); add single-jar system CL escape hatch; test knob scoped to manifest-libs\n- client: pass-through of btrace.* props to agent using $ system props\n- extension: add ClassLoadingUtil and MethodHandleCache for provided-style extensions\n- examples: add btrace-extensions/examples/{btrace-spark,btrace-hadoop} with README\n- docs: research + provided-style guide + migration + examples index; README deprecation note\n- tests: add ManifestLibsTests; gradle knob for btrace.test.skipLibs\n\nBREAKING CHANGE: libs/profiles deprecated with planned removal after N+2; prefer extensions
- Proactively retransform java.lang.Thread after startup scripts load
- Move initExtensions() after transformer is installed
- Add delay in RuntimeTest to allow traced app output after ready marker

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ation

- Add disconnecting flag to RemoteClient for immediate probe visibility
- Skip loadAgent when agent already running (check btrace.port)
- Add try-finally cleanup in tests to prevent port conflicts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces provided-style extensions and manifest-driven library loading to enable tracing application-specific classes without polluting the application classpath. The core innovation is using reflection and object hand-off patterns to access application classes at runtime, keeping BTrace isolated.

Changes:

  • New extension utilities (ClassLoadingUtil, MethodHandleCache) for runtime class resolution and reflective method access
  • Manifest-driven library path resolution (AgentManifestLibs) with security restrictions to BTRACE_HOME
  • Refactored agent classpath processing with deduplication and better error handling
  • Example extensions for Spark and Hadoop demonstrating the provided-style pattern
  • Comprehensive architecture documentation and migration guides
  • Deprecation of libs/profiles mechanism with escape hatch for edge cases

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
settings.gradle Added example extension modules (btrace-spark, btrace-hadoop)
integration-tests/src/test/java/tests/RuntimeTest.java Fixed debug flag insertion and added timing delays for test stability
integration-tests/src/test/java/tests/ManifestLibsTests.java New test suite for manifest-libs feature
integration-tests/src/test/java/tests/BTraceFunctionalTests.java Improved unattended test with better synchronization and cleanup
integration-tests/build.gradle Added test property for skipping preconfigured libs
docs/examples/README.md Guide for building and configuring provided-style extension examples
docs/architecture/provided-style-extensions.md Comprehensive guide on provided-style extension pattern
docs/architecture/migrating-from-libs-profiles.md Migration guide from deprecated libs/profiles to extensions
docs/architecture/agent-manifest-libs.md Design document for manifest-driven library loading
compile.log Build artifact that should not be committed
btrace-extensions/examples/btrace-spark/* Example Spark extension with API and provided-style implementation
btrace-extensions/examples/btrace-hadoop/* Example Hadoop extension with API and provided-style implementation
btrace-extension/src/main/java/org/openjdk/btrace/extension/util/MethodHandleCache.java Cache for reflective method handles to reduce lookup overhead
btrace-extension/src/main/java/org/openjdk/btrace/extension/util/ClassLoadingUtil.java Helper utilities for TCCL-based class loading and service discovery
btrace-client/src/main/java/org/openjdk/btrace/client/Main.java Removed exit hooks for list-only operations to prevent unintended probe removal
btrace-client/src/main/java/org/openjdk/btrace/client/Client.java Added agent-already-running detection and system property pass-through
btrace-agent/src/main/java/org/openjdk/btrace/agent/RemoteClient.java Improved disconnect handling with disconnecting flag
btrace-agent/src/main/java/org/openjdk/btrace/agent/Main.java Refactored classpath processing with manifest support, deduplication, and escape hatch for single-jar injection
btrace-agent/src/main/java/org/openjdk/btrace/agent/AgentManifestLibs.java New utility for manifest-driven library resolution with security checks
README.md Added deprecation notice for libs/profiles with migration guidance

boolean ignore = Boolean.getBoolean("btrace.ignoreManifestLibs");
if (ignore) {
if (log.isDebugEnabled()) log.debug("Ignoring manifest libs (btrace.ignoreManifestLibs=true)");
return new ResolvedLibs(List.of(), List.of());
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code uses List.of() which was introduced in Java 9, but the project targets Java 8 (as specified in source/target compatibility and the coding guidelines). This will cause a compilation error when building with Java 8. Use Collections.emptyList() or Arrays.asList() instead for Java 8 compatibility.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Manifest mf = readManifest(anchor);
if (mf == null) {
if (log.isDebugEnabled()) log.debug("No manifest found for agent; skipping manifest libs");
return new ResolvedLibs(List.of(), List.of());
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code uses List.of() which was introduced in Java 9, but the project targets Java 8. This will cause a compilation error. Use Collections.emptyList() or Arrays.asList() instead for Java 8 compatibility.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

}

/** Attempts to load a class by name using the given preferred loader, then TCCL, then system. */
public static Class<?> load(String className, ClassLoader preferred) throws ClassNotFoundException {
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method ClassLoadingUtil.load(..) could be confused with overloaded method load, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Jan 13, 2026

@jbachorik I've opened a new pull request, #792, to work on those changes. Once the pull request is ready, I'll request review from you.

…il/ClassLoadingUtil.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Jan 13, 2026

@jbachorik I've opened a new pull request, #793, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Jan 13, 2026

@jbachorik I've opened a new pull request, #794, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 2 commits January 14, 2026 09:55
…usion

Co-authored-by: jbachorik <738413+jbachorik@users.noreply.github.com>
… compatibility

Co-authored-by: jbachorik <738413+jbachorik@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI AI-generated code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants