Skip to content

Replace byte-buddy with ASM for runtime method interception#2310

Open
colinmarsch wants to merge 2 commits intomasterfrom
byte-buddy-to-asm-migration
Open

Replace byte-buddy with ASM for runtime method interception#2310
colinmarsch wants to merge 2 commits intomasterfrom
byte-buddy-to-asm-migration

Conversation

@colinmarsch
Copy link
Copy Markdown
Collaborator

Summary

Byte-buddy (byte-buddy + byte-buddy-agent, ~3.5 MB) was used solely for one thing: redefining View.isInEditMode() at runtime via InterceptorRegistrar. This replaces both dependencies with direct ASM bytecode transformation and the JDK Attach/Instrumentation APIs.

Why: byte-buddy is a large, general-purpose bytecode library. Paparazzi's interception needs are minimal (replace a method body with a static delegate call), so ASM's lower-level API is a better fit — smaller dependency footprint, fewer transitive deps, and more transparent bytecode manipulation.

What changed

  • AgentInstaller.kt (new) — self-attaches to the current JVM via VirtualMachine.attach() to obtain a java.lang.instrument.Instrumentation instance. Replaces ByteBuddyAgent.install().
  • InterceptorRegistrar.kt (rewritten) — uses ASM ClassReader/ClassWriter/ClassVisitor to rewrite target method bodies with INVOKESTATIC calls to interceptor classes. Uses Instrumentation.retransformClasses() (not redefineClasses) to apply transforms, which ensures compatibility with classes already modified by build-time ASM transforms.
  • PaparazziSdk.kt — removed ByteBuddyAgent.install() call; agent installation is now handled internally by InterceptorRegistrar.registerMethodInterceptors().
  • PaparazziPlugin.kt — adds -Djdk.attach.allowAttachSelf=true and -XX:+EnableDynamicAgentLoading JVM flags to consumer test tasks (required for the JDK Attach API).
  • libs.versions.toml / build.gradle — replaced bytebuddy-agent + bytebuddy-core with org.ow2.asm:asm:9.7.1.

Test plan

  • InterceptorRegistrarTest passes — verifies ASM-based method interception and class retransformation
  • All :paparazzi:test tests pass
  • :sample:testDebug passes — full end-to-end: agent install → ASM transform of android.view.View.isInEditMode() → layoutlib rendering → snapshot comparison

🤖 Generated with Claude Code

colinmarsch and others added 2 commits March 16, 2026 21:49
Byte-buddy was used solely for redefining class methods at runtime
(e.g., intercepting View.isInEditMode()). This replaces it with
direct ASM bytecode transformation + JDK Attach/Instrumentation APIs,
removing ~2 transitive dependencies.

Key changes:
- AgentInstaller: self-attaches via VirtualMachine to obtain
  Instrumentation, replacing ByteBuddyAgent.install()
- InterceptorRegistrar: uses ASM ClassVisitor to rewrite method
  bodies and Instrumentation.retransformClasses() to apply them,
  replacing ByteBuddy's redefine/MethodDelegation
- retransformClasses (not redefineClasses) ensures compatibility
  with classes already modified by build-time ASM transforms
- JVM flags -Djdk.attach.allowAttachSelf=true and
  -XX:+EnableDynamicAgentLoading added to test tasks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jrodbx jrodbx added this to the 2.0.0-alpha06 milestone Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants