Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Byteman Project main repo

Fetching latest commit…

Cannot retrieve the latest commit at this time

README
Byteman 1.0.2 README
------------------

Byteman supports injection of side effects into Java programs for the
purpose of tsting application behaviour.

If you have downloaded a binary release then the byteman jar can be found
in

  lib/byteman.jar

If you have downloaded a source release then type 'ant jar' to build
the byteman jar. It will be found in

  build/lib/byteman.jar

A summary of how to use Byteman is provided below. For full details of
the operation of Byteman consult the user guide in

  docs/ProgrammersGuide.pdf

Set up and Execution
--------------------
In order to use this library you need to supply JVM with the
byteman jar as a java agent. This jar implements

  an agent class which monitors bytecode load operations and selects
  classes which match the compiled rule set as candidates for
  transformation

  the transformer class which inserts trigger calls to invoke rules

  a rule compiler which translates rules into classes which handle the
  trigger method calls

The agent is passed to the JVM using the -javaagent option of the java
command by setting JAVA_OPTS as follows:

export JAVA_OPTS="-javaagent:<...>/byteman.jar=script:<...>myscript.txt"

where the ellipsis <...> is replaced with a suitable path to the jar
and script files.

The =script:<scriptFile> option to the -javaagent argument tells the
agent to search <scriptFile> for rules. Multiple scripts may be
supplied by repeating the =script:<scriptFile> argument separated by a
','. The agent will parse each script file to identify rules to be
triggered from methods occurring in application classes.

By default the rule engine executes rule bindings, conditions and
actions by interpreting the rule parse tree. However, byteman also
supports compiled execution. If system property

  org.jboss.byteman.compileToBytecode

is set to a non-null value then the rule engine will compile the rule
bindings, condition and action into Java bytecode which will be
executed when the rule is triggered (see the user guide for full
details). For rules which are triggered repeatedly during an
application run this should significantly mitigate the overheads
imposed by the rule system.

Calls to builtin method debug normally do not generate output. However
debug prinotut to System.out can be enabled by setting system property
on the java command line.

  org.jboss.byteman.debug

If more verbose output is desired then property

  org.jboss.byteman.verbose

can be set. This enables debug output from rule scripts and also
traces various of the actions performed by the byteman agent.

The agent can be configured to dump transformed byte code by setting
several Java system properties as shown in the example above:

  org.jboss.byteman.dump.generated.classes

this can be set to any value to enable dumping of generated
code. Files will be written in a directory tree correspnding to the
package hierarchy for the associated class.

  org.jboss.byteman.dump.generated.classes.directory

this can be set to a directory below which files will be written. if
unset files are written to the current working directory of the JVM
thread executing the transformer code.

Rule Definition
---------------

The byteman package employs Event Condition Action rules. The
event component is limited to matching an invocation of a specific
method when execution reaches a particular location in the method
body. The event automatically binds the arguments of the trigger
method at the point where the rule is triggered. It may also compute
bindings for an optional set of local variables by evaluating a Java
expression. The condition is an expression with boolean type. The
action is a sequence of expressions of arbitrary type which are only
evaluated if the condition is true. Expressions are composed from
builtin operations, references to static or bound values, method
invocations and combinations of sub-expressions using the usual set of
operators. Note that assignment, new operations and throw operations
are not allowed in expressions.

Rule definitions specify a target class, a target method and a target
location in the method source code. Locations can be identified by
various means, includign entry to the method, a specific line number,
or points where field reads/writes or subordinate method invocations
occur. The agent code identifies classes and methods at load time
which match the target class and name and inserts a trigger call at
the specified location which invokes the rule. When execution reaches
a trigger point the associated rule is executed and can performs any
delay, synchronization, trace or other operation appropriate to the
test. Normally, control returns to the trigger method and execution
continues by executing the target line.

It is possible for a rule to alter the flow of control. A rule action
may employ the return builtin to force a return from the triggering
method at the point where the trigger call was made. If the triggering
method is is not void then the return expression must include an
argument whose type is compatible with the method return type. A rule
action can also invoke a builtin to 'kill' the current thread, by
throwing a runtime exception. This may not actually kill the thread if
the trigger method code or one of its callers catches a generic
exception but it can still be used effectively in many cases. Another
builtin can be used to signal other waiting threads and cause them to
'abort'. Finally, a third builtin allows the JVM to be halted. It is
possible to call arbitrary Java code inside rule actions so the
opportunites for messing around with control flow extend beyond these
builtin options.

The target class may be specified with or without a full package
qualification. If no package is specified then all classes whose
unqualified name equals the target will be candidiates for rule
trigger insertion. Note, however, that for safety triggers will not be
inserted into java.lang or org.jboss.byteman classes.

Class names mentioned in rules are resolved against a candidate
trigger class and related classes at runtime as they are being loaded
into a specific class loader. If the type checker cannot resolve the
declared types of variables, methods and fields mentioned in the rule
against candidate classes it prints type check errors and disables
execution of the rule for the class in question. Note that if a class
is loaded more than once by different class loaders then each version
of the class may be a candidate for trigger insertion from the same
rule. Use of unqualified class names (i.e. without package) also
potentially allows a rule to be applied in more than one case.

Method names may be specified using just the method name or by
supplying the name and a bracketed list of parameters, optionally
followed by a return type. If just the name is specified then any
method with the correct name will be considered as a candidate for
trigger insertion. Again, this allows the rule to be applied to
multiple cases (this is only really useful if the line number is -1).
If a signature is provided then the trigger call will only be inserted
into a method whose arguments match the signature. The types employed
in a signature may also omit the package name if desired.

Note that a rule is deliberately defined via a script rather than
using annotations, especially not annotations on the trigger class.
Rules refer to the target class and, possibly, classes that it
references by name only. Defining the rule via annotations on the
target class implementation would require loading the class before
having the chance to modify its byte code. Also, the point of using
rules is so that tests may be rigged up without having to redefine and
rebuild the test code base.

Rule Events
-----------
An event specification comprises a location specification and a set of
bindings. All location specification declare a target class and target
method using the syntax

CLASS <classname>
METHOD <methodname>

Class names may omit the package qualifier in which case the rule will
apply to any class whose unqualified name matches. The method name may
also specify or omit a brackted list of comma-separated argument
types.

Location specifications also include a further qualifier identifying
where in the target method the trigger point for the rule should be
located. The simplest location specification is AT ENTRY which locates
the triggerpoint at the first executable instruction in a the atrget
method's bytecode (or the first instruction following the superclass
constructor if the target method is a constructor). The full list of
qualifiers is

AT ENTRY
AT EXIT
AT LINE <number>
AT READ <fieldname> [<count>]
AT WRITE <fieldname> [<count>]
AT INVOKE <methodname>[[signature>] [<count>]
AT SYNCHRONIZE [<count>]
AT THROW [<typename>] [<count>]

An event specification also includes a list of bindings for variables
which can be referenced during evaluaton of the rule condition and
execution of the rule actions. Bindings are established in the context
of the target method. By default, the target method arguments are
pre-bound using the special syntax $0 (for this, when the target
method is not static) and $1...$N for arguments 1..N of the
method. The value of local variables in scope at the trigger point may
be referenced by prefixing the varable name with a dollar sign e.g. if
the trigger point occurs inside a for loop with loop variable i then
the loop ndex may be accessed using name $i. Further bindings,
employing standard alphanumeric names for the bound variables, can be
established by assigning a name to an expression which may refer to
previously bound variables or static data. For example,

  'BIND coordinator:Coordinator = $0,
   recovered:boolean = coordinator.recovered,
   identifier:String = coordinator.getInstanceIdentifier()'

binds coordinator to the Coordinator instance bound to this in the
triggering method, binds recovered to the value of its boolean field,
recovered, and binds identifier to the String returned by invoking
method getInstanceIdentifier().

The LHS of a binding must be a variable name or a name:type pair. If
the type is omitted it will be inferred from the RHS where
possible. The RHS of a binding is a Java expression which can include
various builtin expressions plus most Java expressions such as static
or instance field accesses and invocations, array dereferences,
operator expressions, method invocations, etc (but *not* assignment
expressions). The RHS of a binding may refer to method argument
variables, method local variables in scope at the trigger point and
variables bound in earlier bindings. The RHS may not refer to its own
LHS variable or later bound variables. Rebinding of variables is not
permitted.

Rule Conditions
---------------
A condition is merely an expression with a boolean result. Expressions
may be complex using the usual operators plus a few syntactically
sugared variants. Conditions may also include method invocations and
references to bound variables. So, for example:

  'engine.isRecovered() AND getCountdown(instanceIdentifier)'

will succeed if engine.isRecovered() returns true and a countdown
identified by instanceIdentifer is active

  'NOT recovered && countDown(instanceIdentifier)'

will succeed if recovered is false and decrementing the countdown
identified by instanceIdentifier renders it inactive.

Rule Actions
------------
An action is a series of expressions which are either method
invocations or builtin invocations. Actions may include references to
bound variables. So, for example,

  'debug("killing prepare attempt"), killThread()'

will print a debug message and abort the target method with a runtime
exception, killing the therad in normal circumstances

  'debug("terminator X it"), killJVM()'

will print a debug message and cause an immediate halt of the JVM.
Debug printout must be enabled by setting System property

  org.jboss.byteman.debug

on the java command line.

Expressions
-----------
Expressions occuring in rules can employ most of the available Java
syntax with the notable exception that assignment is only valid at the
top level in an event binding. Certain restrictions currently apply
e.g. the recipient of a method invocation must be either a bound
variable (*not* a dollar variable) or a field reference or series of
field references via a bound vaiable or a static field reference
(e.g. foo.meth(), foo.bar.meth, com.arjuna.foo.meth()). These should
get fixed at some point.

A variety of builtin methods are available. These may be written as
function calls although internally they are treated as invocations of
instance methods on an object identified by an implicit bound variable
$$ of type Rule.Helper. Each time a rule is triggered a Helper
instance is used to store the table of bindings for any trigger method
arguments $0, $1 etc, local variables mentioned in the rule and event
variables explicitly bound by the rule. Every public instance method
on class Helper is automatically available as a callable function in a
rule binding, condition or action. For example, Helper defines a
boolean method debug(String) which prints text to System.out. So, a
call to debug("call to debug") will result in a call to the helper's
instance method (n.b. debug always returns true, allowing it to be
composed in AND conditions as well invoked as an action).

Helper provides other builtins which perform thread synchronization
operations, manage rule system state which coordinates actions across
independent rule firings and tarces execution of rules. Methods to
support rendezvous will be added soon. It is possible to specify per
rule that an alternative Helper class should be employed, enabling
test-specific builtin operations to be used where appropriate. This is achieved by adding a line in the format

  HELPER <classname>

before the location specifier (AT XXX) in the rule definition. Any
public methdos of the supplied class will be available for use as
builtin methods in the rule body. n.b. it is usually best to supply a
class which extends the built-in class Helper as this will
conservatively extend (or possibly override) the default set of
builtpin operations.

Type Checking Scripts
---------------------
Rule scripts may be checked offline by running the bash shell script
bytemancheck.sh located in the bin directory. See the script header
for details.

Documentation
-------------
For full details of rule syntax the operation of the byteman
package see the manual in the docs directory.

Copyright
---------
See the copyright file in the docs directory for details of the open
source license under which this code is released. Note that this code
employs the ObjectWeb ASM package to do bytecode manipulation and the
JFlex and JavaCUP tokeniser and parser genereators to generate and
provide runtime support for the rule parser which are also released
under open source licenses.

Something went wrong with that request. Please try again.