| Sign In/My Account | View Cart |
Introduction to the ASM 2.0 Bytecode Framework
Pages: 1, 2, 3, 4, 5, 6, 7, 8
Here are a few things to notice:
As you can see, bytecode tweaking isn't easy. However, the ASM framework reduces the complexity of the underlying structures and provides a simplified API that still allows for access to all bytecode information and enables complex transformations.
The Core package uses a push approach (similar to the "Visitor" design
pattern, which is also used in the SAX API for XML processing) to walk
trough complex bytecode structures. ASM defines several interfaces,
such as ClassVisitor (section [1] in the class file format diagram above),
FieldVisitor (section [2]), MethodVisitor
(section [3]), and AnnotationVisitor.
AnnotationVisitor is a special interface that allows
you to express hierarchical annotation structures. The next few
paragraphs will show how these interfaces interact with each other
and how they can be used together to implement bytecode
transformations and/or capture information from the bytecode.
The Core package can be logically divided into two major parts:
ClassReader or a
custom class that can fire the proper sequence of calls to the methods
of the above visitor classes.ClassWriter,
FieldWriter, MethodWriter, and
AnnotationWriter), adapters (ClassAdapter
and MethodAdapter), or any other classes implementing
the above visitor interfaces.Figure 2 shows the sequence diagram for the common producer-consumer interaction.

Figure 2. Sequence diagram for producer-consumer
interaction
In this interaction, 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. When
a producer receive a null value for FieldVisitor or
MethodVisitor, it skips that fragment of the class
(e.g., a ClassReader wouldn't even parse the
corresponding bytecode section in such a case, which leads to a
sort of "lazy loading" feature driven by the visitors). Otherwise,
the corresponding subcontext events are delegated to the child
visitor instance. At the end of each subcontext, the producer calls
the visitEnd() method and then moves on to the next
section (e.g., the next field, method, etc.).