Information Technology Reference
In-Depth Information
Dynamic instrumentation of bytecode is
typically more straightforward than dynamic
instrumentation of low-level machine instructions
because of the higher level of abstraction. More-
over, modifying bytecode provides a more portable
solution that is largely agnostic to the underlying
operating system and hardware platform.
Within the context of Java, the JVMTI provides
a method known as RedefineClasses() that a
profiler agent can use to insert “new” bytecode into
an existing class. When this method is invoked,
the JVM performs all the steps needed to load a
class, parse the class code, create objects of the
class, and initializes them. After these steps are
complete, the JVM performs hot-swapping by
suspending all threads and replacing the class,
while ensuring that all pointers are updated to
point to the new object (Dmitriev, 2001).
These dynamic instrumentation activities can
incur significant overhead in production environ-
ments and thus must be accounted for accord-
ingly. Some research is investigating techniques
to minimize the overhead incurred by dynamic
instrumentation. For example, work by Dmitriev
(2002) is investigating the use of “method swap-
ping” so that bytecode replacement can be done
at a finer granularity than class-level replacement.
Similar techniques are also being explored within
the context of the .NET platform (Vaswani &
Srikant, 2003).
A number of tools have been developed to
help instrument bytecode, much like the Pin API
described earlier. Examples include BIT (Lee,
1997) and IBM's Jikes Bytecode Toolkit (IBM
Corporation, 2000). These tools shield application
developers from the complexity of bytecode by
providing an API that can be used to parse and
modify it.
a in- d l o a d t i m e i in- s t r u m e in- t a t i o in- . D y in- a m i c i in- -
strumentation also requires creating “new”
objects of the “new” classes correspond-
ing to all “old” objects in the application,
initializing their state to the state of the old
object, suspend the running threads, and
switching all pointers to the “old” objects to
the “new” objects. This replacement process
is complicated, so application state may be
inconsistent after the operation, which can
cause incorrect behavior.
Static and load-time instrumentation are
generally easier to implement than dynamic
instrumentation because they need not
worry about the consistency of a running
application. Dynamic instrumentation has
a broader range of applicability, however, if
done efficiently. Current research (Dmitriev,
2002, 2004) is focusing on how to make
dynamic instrumentation more efficient and
less complicated.
aspect-oriented techniques used
for instrumentation
Although explicit bytecode instrumentation is
more flexible and incurs less overhead than VM
hooks, the implementation complexity is higher
because developers must be highly skilled in
bytecode syntax to instrument it effectively with-
out corrupting application code. Aspect-oriented
Programming (AOP) helps remove this complexity
and enables bytecode instrumenting at a higher
level of abstraction. Developers can therefore
focus on the logic of the code snippets and the
appropriate insertion points, rather than wrestling
with low-level implementation details (Davies,
Huismans, Slaney, Whiting, & Webster, 2003).
Relevant AOP concepts include (1) join-points,
which define placeholders for instru mentation
within application code, (2) point-cuts, which
identify a selection of join-points to instrument,
and (3) advice, which specifies the code to insert
at the corresponding join-point.
The three bytecode instrument techniques
(i.e., static, load-time, and dynamic) incur
similar overhead. Dynamic bytecode instru-
mentation is more powerful, but is generally
more complex and error-prone than static
Search WWH ::




Custom Search