JVM tool guide · bytecode

ASM: Read and Rewrite Java Bytecode

ASM is the bedrock bytecode library on the JVM — the JDK itself uses it internally, as do countless frameworks and APM agents. It reads .class files event-by-event and lets you emit or modify bytecode directly with a tiny footprint and zero dependencies.

Where Byte Buddy gives you a fluent high-level API, ASM gives you the opcodes. It is the right tool when you need precise, fast class rewriting or code generation and can tolerate writing the lower-level visitors.

Official ASM project

Use it when

• You need to modify class files at build time or load time (agents, build plugins).

• You're generating small, tight bytecode and want full control over each instruction.

• You want to analyze class structure (methods, fields, annotations) programmatically.

Skip it when

• You want a readable, high-level API for dynamic proxies — Byte Buddy is friendlier.

Read a class with a ClassReader

Crucial for bytecode understanding: visit methods and print the disassembly. The tree API (ClassNode) is more convenient for most rewriting than the event visitor API.

ClassReader cr = new ClassReader(inputStream);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);                       // parse
for (MethodNode m : cn.methods) {
  System.out.println(m.name + m.desc);  // descriptor = signature
}

Generate a method with a ClassWriter

Emit instructions with the visitor pattern. ASM provides an mnemonics helper (MathOps, InsnList) so opcodes are typed rather than raw bytes.

ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V1_8, ACC_PUBLIC, "com/example/Hello",
         null, "java/lang/Object", null);
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 1);
mv.visitEnd();
byte[] bytes = cw.toByteArray();

Transform on load with a Java agent

Use a ClassFileTransformer in a premain to rewrite bytes for every matching class loaded by the JVM — the hook ASM-based agents use to instrument applications.

public byte[] transform(Module mod, ClassLoader cl,
    String name, Class<?> cf, ProtectionDomain pd, byte[] bytes) {
  if (!name.startsWith("com/example/")) return bytes;
  ClassReader cr = new ClassReader(bytes);
  ClassWriter cw = new ClassWriter(0);
  cr.accept(new MyClassVisitor(cw), 0);
  return cw.toByteArray();
}
Quick start

Get productive in minutes

Disassemble any class

Read and dump the constant pool and instructions.

ClassNode cn = new ClassNode();
new ClassReader(bytes).accept(cn, 0);
System.out.println(cn.name);
cn.methods.forEach(m -> System.out.println(m.name + m.desc));

Frequently asked questions

ASM vs Byte Buddy?

Byte Buddy is built on ASM. Use Byte Buddy for dynamic proxies and ergonomic code generation; use ASM directly for maximal control, minimal footprint, or when you're instrumenting at the instruction level.

Does ASM keep up with new JDKs?

Yes — new ASM versions support each new class-file version, including records, sealed classes, pattern matching, and virtual-thread-related updates. Match the ASM major version to your class-file target.

Last updated August 2026 · JVM Tools is independent and not affiliated with Oracle.