ASM: A Bytecode Manipulation
Tool – A brief Overview
Course : CSE 6329
Spring 2011
University of Texas at Arlington
• Presented by
• Sarker Tanveer Ahmed Rumee
• All the tables and figures of this presentation was
copied from the publicly available ASM- Guide from
the ASM website.
• Some contents were also copied from the
ASM 2.0 tutorial.
What is ASM?
• ASM is an all purpose Java Bytecode
manipulation and analysis framework.
• It can be used to modify existing classes or
dynamically generate classes, directly in
binary form.
Where to find?
• The ASM Home Page
– It contains the ASM library for download
– Also has links to documents and other resources
– To download the current stable version of ASM
library go to the following link:
Online Documentation and Resources
• ASM Guide [API Reference and Detail
Discussion about the use of ASM].
• API Reference
Bytecode Outline Plugin
• Start Eclipse
• Go to: Help->Install new software
• In the Location bar enter the following
– It will show available updates
– Select the Bytecode Outline and rest of the steps
are trivial
A Very short Overview of JAVA
Class File Format
Structure of Compiled Java Class
Few Facts
• Compiled class describes only one class where
a source file may contain several classes
• Compiled class does not contain comments
• A compiled class does not contain package
and import section, so all type names must be
fully qualified. For example:
– Fully Qualified name of String is java/lang/String
• NB: In this form Dots (.) are replaced by Slash (/)
Few Facts (Contd..)
• Internal names are used for class and interface
types. Internal name is nothing but the fully
qualified name of the class/interface.
• In all other situations java types are
represented in compiled classes with type
Type Descriptors
Method Descriptors
ASM Framework
• The ASM bytecode manipulation framework is
written in Java and uses a visitor-based
• Allows developers to avoid dealing directly
with a class constant pool and offsets within
method byte code.
• Provides better performance, compared to
other tools such as BCEL, SERP, orJavassist.
ASM package structure
• ASM is divided into several packages. The
package structure is :
ASM package structure (Contd..)
• The Core package provides an API to read, write, and
transform Java bytecode and defines a foundation for the
other packages. This package is sufficient to generate Java
bytecode and to implement the majority of bytecode
• The Tree package provides in-memory representation of Java
• The Analysis package provides basic data-flow analyses and
type-checking algorithms for Java method bytecode stored in
structures from the tree package.
• The Commons package (added in ASM 2.0)
provides several commonly used bytecode
transformations and adapters to simplify
bytecode generation.
• The Util package contains several helper classes
and simple bytecode verifiers that can help in
development or testing.
• The XML package provides an adapter to convert
bytecode structures to and from XML
The Core Package
• The Core package uses a push approach
(similar to the "Visitor" design pattern) to walk
trough complex bytecode structures.
• ASM defines several interfaces, such as
ClassVisitor , FieldVisitor , MethodVisitor and
• These interfaces interact with each other to
implement bytecode transformations and/or
capture information from the bytecode.
Core package [cont..]
• The Core package can be logically divided into
two major parts:
– Bytecode producers, such as a ClassReader or a
custom class that can fire the proper sequence of
calls to the methods of the above visitor classes.
– Bytecode consumers, such as writers
(ClassWriter, FieldWriter, MethodWriter,
and AnnotationWriter), adapters
(ClassAdapter and MethodAdapter), or any other
classes implementing the above visitor interfaces.
Visitor Design Pattern
• ASM follows the Visitor Design Pattern for its
• To understand how it works we need to
investigate how the Visitor Design Pattern fits
in Object Oriented Programming.
Visitor Design Pattern
• In object-oriented programming and software
engineering, the visitor design pattern is a
way of separating an algorithm from an object
structure it operates on.
• A practical result of this separation is the
ability to add new operations to existing
object structures without modifying those
The participating classes
 Visitor - This is an interface used to declare the visit
operations for all the types of visitable classes. Usually the
name of the operation is the same and the operations are
differentiated by the method signature.
 ConcreteVisitor - An implementation of Visitor that
implements all the visit method
 Visitable - is an abstraction which declares the accept
operation. This is the entry point which enables an object to
be "visited" by the visitor object.
 ConcreteVisitable - Those classes implementing the Visitable
interface or a class and defines the accept operation.
Visitor Design Pattern [cont..]
• We want to add “print” method for each of
the following classes representing different
parts of a Car
– Wheel, Engine, and Body
– Instead of creating "print" methods for each
subclass (Wheel, Engine, Body), a single class
(CarElementPrintVisitor) will be used to perform
the required printing action
interface CarElementVisitor {
void visit(Wheel wheel);
void visit(Engine engine);
void visit(Body body);
 Visitable
interface CarElement {
void accept(CarElementVisitor visitor); //
CarElements have to provide accept().
class Wheel implements CarElement {
public void accept(CarElementVisitor visitor) {
class Engine implements CarElement {
public void accept(CarElementVisitor visitor) {
class Body implements CarElement {
accept(..) {} }
class CarElementPrintVisitor implements CarElementVisitor {
public void visit(Wheel wheel) {
System.out.println("Visiting wheel");
public void visit(Engine engine) {
System.out.println("Visiting engine");
public void visit(Body body) {
System.out.println("Visiting body");
public class VisitorDemo {
static public void main(String[] args){
Wheel ob1 = new Wheel();
Body ob2 = new Body();
Engine ob3 = new Engine();
ob1.accept(new CarElementVisitor());
ob2.accept(new CarElementVisitor());
ob3.accept(new CarElementVisitor());
Using ASM API to write Code
• ASM API for generating and transforming
compiled classes is based on ClassVisitor
• Each method of this interface correspond to
the class file structure described earlier
• The ClassVisitor interface is depicted in the
next slide.
ClassVisitor Interface
ClassVisitor (cont..)
• Simple sections of a class are visited by a
single method call and it returns void
• Sections whose content can be of arbitrary
length are visited with a initial method call
that returns an auxiliary interface. This
happens for visitAnnotation, visitField and
• The auxiliary visitor interfaces will be
described later.
How it works
• A client application creates ClassReader and calls
the accept() method, passing a
concrete ClassVisitor instance as a parameter.
• Then ClassReader parses the class and fires "visit" events
to ClassVisitor for each bytecode fragment
• For repeated contexts, such as fields, methods, or
annotations, a ClassVisitor may create child visitors
derived from the corresponding interface
(FieldVisitor,MethodVisitor, or AnnotationVisitor) and
return them to the producer.
• The methods of the ClassVisitor interface
must be called in the following order:
visit visitSource? visitOuterClass?
(visitAnnotation | visitAttribute) *
(visitInnerClass | visitField | visit Method )*
Three Core Components
• ASM provides three core components based
on ClassVisitor interface in order to generate
and transform classes. These are:
– ClassReader
– ClassWriter
– ClassAdapter
Three Main tasks of ASM Tool
• Parse a class
• Generate a class
• Transform a class
– We discuss these three tasks in light of the three
core components depicted in the previous class.
Parsing Classes
• Only required component to parse and
existing class is the ClassReader
• It does so by calling the corresponding visitXxx
methods on ClassVisitor instance passed as an
argument to its accept method.
• Let’s see an example how it works.
Parsing a Class using ClassReader
• Example:
Generating Classes
• The only required component – ClassWriter
• It is an implementation of the ClassVisitor
interface that builds compiled classes directly
in binary form.
• It produce as output a byte array that contains
the compiled class
• Lets’ see and example:
Generating Classes (cont..)
• Consider the following interface
Generating Classes (cont..)
• The Above interface can be generated with 6
method calls to a ClassVisitor
• Lets’ see the example..
Transforming classes
• So far we have used ClassReader and
ClassWriter separately.
• The events were produced by “hand ” and
consumed directly by a ClassWriter or,
Symmetrically, or Events were produced by
ClassReader and consumed by “hand”. i.e, by a
custom ClassVisitor implementation.
Transforming Classes (cont..)
• Now we want to use both ClassReader and
ClassWriter together.
• The first step would be to direct the events
produced by a ClassReader to a ClassWriter,
the result is that the class parsed by the
ClassReader is reconstructed by the
Transforming Classes (cont..)
• So the corresponding code fragment will be:
Introduction of ClassAdapter
• Now we introduce a middle entity named
ClassAdapter. The idea will be:
ClassAdapter (cont..)
ClassAdapter (cont..)
• According to the code fragment depicted
above the outcome does not change, because
the ClassAdapter does not filter anything
• But now we can easily filter some events using
the ClassAdapter to Transform a class.
Example on Class Transformation
• We have discussed so far three basic
operations that can be done by ASM
• But ASM library has a large collection of useful
API to help analysis Compiled java classes in
great detail.
• The ASM –GUIDE is very good resource in this

similar documents