Top Description Fields Constructors Methods
org.objectweb.asm.tree.analysis

public Class Analyzer<V extends Value>

extends Object
implements Opcodes
Class Inheritance
All Implemented Interfaces
org.objectweb.asm.Opcodes
Type Parameters
<V>
type of the Value used for the analysis.
Imports
java.util.ArrayList, .HashMap, .List, .Map, org.objectweb.asm.Opcodes, .Type, org.objectweb.asm.tree.AbstractInsnNode, .IincInsnNode, .InsnList, .JumpInsnNode, .LabelNode, .LookupSwitchInsnNode, .MethodNode, .TableSwitchInsnNode, .TryCatchBlockNode, .VarInsnNode

A semantic bytecode analyzer. This class does not fully check that JSR and RET instructions are valid.
Author
Eric Bruneton

Field Summary

Modifier and TypeField and Description
private Frame<V>[]
frames

The execution stack frames of the currently analyzed method (one per instruction index).

private List<TryCatchBlockNode>[]
handlers

The exception handlers of the currently analyzed method (one list per instruction index).

private boolean[]
inInstructionsToProcess

The instructions that remain to process (one boolean per instruction index).

private InsnList
insnList

The instructions of the currently analyzed method.

private int
insnListSize

The size of insnList.

private int[]
instructionsToProcess

The indices of the instructions that remain to process in the currently analyzed method.

private final Interpreter<V>
interpreter

The interpreter to use to symbolically interpret the bytecode instructions.

private int
numInstructionsToProcess

The number of instructions that remain to process in the currently analyzed method.

private Subroutine[]
subroutines

The subroutines of the currently analyzed method (one per instruction index).

Constructor Summary

AccessConstructor and Description
public
Analyzer(final Interpreter<V>
the interpreter to use to symbolically interpret the bytecode instructions.
interpreter
)

Constructs a new Analyzer.

Method Summary

Modifier and TypeMethod and Description
public Frame<V>[]

Returns:

the symbolic state of the execution stack frame at each bytecode instruction of the method. The size of the returned array is equal to the number of instructions (and labels) of the method. A given frame is null if and only if the corresponding instruction cannot be reached (dead code).
analyze
(final String
the internal name of the class to which 'method' belongs (see Type#getInternalName()).
owner
,
final MethodNode
the method to be analyzed. The maxStack and maxLocals fields must have correct values.
method
)

Analyzes the given method.

public Frame<V>[]

Returns:

the symbolic state of the execution stack frame at each bytecode instruction of the method. The size of the returned array is equal to the number of instructions (and labels) of the method. A given frame is null if and only if the corresponding instruction cannot be reached (dead code).
analyzeAndComputeMaxs
(final String
the internal name of the class to which 'method' belongs (see Type#getInternalName()).
owner
,
final MethodNode
the method to be analyzed.
method
)

Analyzes the given method and computes and sets its maximum stack size and maximum number of local variables.

private Frame<V>

Returns:

the initial execution stack frame of the 'method'.
computeInitialFrame
(final String
the internal name of the class to which 'method' belongs (see Type#getInternalName()).
owner
,
final MethodNode
the method to be analyzed.
method
)

Computes the initial execution stack frame of the given method.

private static int

Returns:

the maximum number of local variables used in the given method.
computeMaxLocals
(final MethodNode
a method.
method
)

Computes and returns the maximum number of local variables used in the given method.

private static int

Returns:

the maximum stack size of the given method.
computeMaxStack
(final Frame<?>[]
the stack map frames of a method.
frames
)

Computes and returns the maximum stack size of a method, given its stack map frames.

private void
findSubroutine(final int
an instruction index.
insnIndex
,
final Subroutine
a subroutine.
subroutine
,
final List<AbstractInsnNode>
where the jsr instructions for nested subroutines must be put.
jsrInsns
)

Follows the control flow graph of the currently analyzed method, starting at the given instruction index, and stores a copy of the given subroutine in subroutines for each encountered instruction.

private void
findSubroutines(final int
the maximum number of local variables of the currently analyzed method (long and double values count for two variables).
maxLocals
)

Finds the subroutines of the currently analyzed method and stores them in subroutines.

public Frame<V>[]

Returns:

the symbolic state of the execution stack frame at each bytecode instruction of the method. The size of the returned array is equal to the number of instructions (and labels) of the method. A given frame is null if the corresponding instruction cannot be reached, or if an error occurred during the analysis of the method.
getFrames
()

Returns the symbolic execution stack frame for each instruction of the last analyzed method.

public List<TryCatchBlockNode>

Returns:

a list of TryCatchBlockNode objects.
getHandlers
(final int
the index of an instruction of the last analyzed method.
insnIndex
)

Returns the exception handlers for the given instruction.

protected void
init(final String
the internal name of the class to which the method belongs (see Type#getInternalName()).
owner
,
final MethodNode
the method to be analyzed.
method
)

Initializes this analyzer.

private void
merge(final int
an instruction index.
insnIndex
,
final Frame<V>
a frame. This frame is left unchanged by this method.
frame
,
final Subroutine
a subroutine. This subroutine is left unchanged by this method.
subroutine
)

Merges the given frame and subroutine into the frame and subroutines at the given instruction index.

private void
merge(final int
the index of an instruction immediately following a jsr instruction.
insnIndex
,
final Frame<V>
the execution stack frame before the jsr instruction. This frame is merged into 'frameAfterRet'.
frameBeforeJsr
,
final Frame<V>
the execution stack frame after a ret instruction of the subroutine. This frame is merged into the frame at 'insnIndex' (after it has itself been merge with 'frameBeforeJsr').
frameAfterRet
,
final Subroutine
if the jsr is itself part of a subroutine (case of nested subroutine), the subroutine it belongs to.
subroutineBeforeJsr
,
final boolean[]
the local variables read or written in the subroutine.
localsUsed
)

Merges the given frame and subroutine into the frame and subroutines at the given instruction index (case of a RET instruction).

protected void
newControlFlowEdge(final int
an instruction index.
insnIndex
,
final int
index of a successor instruction.
successorIndex
)

Creates a control flow graph edge.

protected boolean

Returns:

true if this edge must be considered in the data flow analysis performed by this analyzer, or false otherwise. The default implementation of this method always returns true.
newControlFlowExceptionEdge
(final int
an instruction index.
insnIndex
,
final int
index of a successor instruction.
successorIndex
)

Creates a control flow graph edge corresponding to an exception handler.

protected boolean

Returns:

true if this edge must be considered in the data flow analysis performed by this analyzer, or false otherwise. The default implementation of this method delegates to newControlFlowExceptionEdge(int, int).
newControlFlowExceptionEdge
(final int
an instruction index.
insnIndex
,
final TryCatchBlockNode
TryCatchBlockNode corresponding to this edge.
tryCatchBlock
)

Creates a control flow graph edge corresponding to an exception handler.

protected Frame<V>

Returns:

the created frame.
newFrame
(final int
the maximum number of local variables of the frame.
numLocals
,
final int
the maximum stack size of the frame.
numStack
)

Constructs a new frame with the given size.

protected Frame<V>

Returns:

the created frame.
newFrame
(final Frame<? extends V>
a frame.
frame
)

Constructs a copy of the given frame.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

framesback to summary
private Frame<V>[] frames

The execution stack frames of the currently analyzed method (one per instruction index).

handlersback to summary
private List<TryCatchBlockNode>[] handlers

The exception handlers of the currently analyzed method (one list per instruction index).

inInstructionsToProcessback to summary
private boolean[] inInstructionsToProcess

The instructions that remain to process (one boolean per instruction index).

insnListback to summary
private InsnList insnList

The instructions of the currently analyzed method.

insnListSizeback to summary
private int insnListSize

The size of insnList.

instructionsToProcessback to summary
private int[] instructionsToProcess

The indices of the instructions that remain to process in the currently analyzed method.

interpreterback to summary
private final Interpreter<V> interpreter

The interpreter to use to symbolically interpret the bytecode instructions.

numInstructionsToProcessback to summary
private int numInstructionsToProcess

The number of instructions that remain to process in the currently analyzed method.

subroutinesback to summary
private Subroutine[] subroutines

The subroutines of the currently analyzed method (one per instruction index).

Constructor Detail

Analyzerback to summary
public Analyzer(final Interpreter<V> interpreter)

Constructs a new Analyzer.

Parameters
interpreter:Interpreter<V>

the interpreter to use to symbolically interpret the bytecode instructions.

Method Detail

analyzeback to summary
public Frame<V>[] analyze(final String owner, final MethodNode method) throws AnalyzerException

Analyzes the given method.

Parameters
owner:String

the internal name of the class to which 'method' belongs (see Type#getInternalName()).

method:MethodNode

the method to be analyzed. The maxStack and maxLocals fields must have correct values.

Returns:Frame<V>[]

the symbolic state of the execution stack frame at each bytecode instruction of the method. The size of the returned array is equal to the number of instructions (and labels) of the method. A given frame is null if and only if the corresponding instruction cannot be reached (dead code).

Annotations
@SuppressWarnings:unchecked
Exceptions
AnalyzerException:
if a problem occurs during the analysis.
analyzeAndComputeMaxsback to summary
public Frame<V>[] analyzeAndComputeMaxs(final String owner, final MethodNode method) throws AnalyzerException

Analyzes the given method and computes and sets its maximum stack size and maximum number of local variables.

Parameters
owner:String

the internal name of the class to which 'method' belongs (see Type#getInternalName()).

method:MethodNode

the method to be analyzed.

Returns:Frame<V>[]

the symbolic state of the execution stack frame at each bytecode instruction of the method. The size of the returned array is equal to the number of instructions (and labels) of the method. A given frame is null if and only if the corresponding instruction cannot be reached (dead code).

Exceptions
AnalyzerException:
if a problem occurs during the analysis.
computeInitialFrameback to summary
private Frame<V> computeInitialFrame(final String owner, final MethodNode method)

Computes the initial execution stack frame of the given method.

Parameters
owner:String

the internal name of the class to which 'method' belongs (see Type#getInternalName()).

method:MethodNode

the method to be analyzed.

Returns:Frame<V>

the initial execution stack frame of the 'method'.

computeMaxLocalsback to summary
private static int computeMaxLocals(final MethodNode method)

Computes and returns the maximum number of local variables used in the given method.

Parameters
method:MethodNode

a method.

Returns:int

the maximum number of local variables used in the given method.

computeMaxStackback to summary
private static int computeMaxStack(final Frame<?>[] frames)

Computes and returns the maximum stack size of a method, given its stack map frames.

Parameters
frames:Frame<?>[]

the stack map frames of a method.

Returns:int

the maximum stack size of the given method.

findSubroutineback to summary
private void findSubroutine(final int insnIndex, final Subroutine subroutine, final List<AbstractInsnNode> jsrInsns) throws AnalyzerException

Follows the control flow graph of the currently analyzed method, starting at the given instruction index, and stores a copy of the given subroutine in subroutines for each encountered instruction. Jumps to nested subroutines are not followed: instead, the corresponding instructions are put in the given list.

Parameters
insnIndex:int

an instruction index.

subroutine:Subroutine

a subroutine.

jsrInsns:List<AbstractInsnNode>

where the jsr instructions for nested subroutines must be put.

Exceptions
AnalyzerException:
if the control flow graph can fall off the end of the code.
findSubroutinesback to summary
private void findSubroutines(final int maxLocals) throws AnalyzerException

Finds the subroutines of the currently analyzed method and stores them in subroutines.

Parameters
maxLocals:int

the maximum number of local variables of the currently analyzed method (long and double values count for two variables).

Exceptions
AnalyzerException:
if the control flow graph can fall off the end of the code.
getFramesback to summary
public Frame<V>[] getFrames()

Returns the symbolic execution stack frame for each instruction of the last analyzed method.

Returns:Frame<V>[]

the symbolic state of the execution stack frame at each bytecode instruction of the method. The size of the returned array is equal to the number of instructions (and labels) of the method. A given frame is null if the corresponding instruction cannot be reached, or if an error occurred during the analysis of the method.

getHandlersback to summary
public List<TryCatchBlockNode> getHandlers(final int insnIndex)

Returns the exception handlers for the given instruction.

Parameters
insnIndex:int

the index of an instruction of the last analyzed method.

Returns:List<TryCatchBlockNode>

a list of TryCatchBlockNode objects.

initback to summary
protected void init(final String owner, final MethodNode method) throws AnalyzerException

Initializes this analyzer. This method is called just before the execution of control flow analysis loop in analyze. The default implementation of this method does nothing.

Parameters
owner:String

the internal name of the class to which the method belongs (see Type#getInternalName()).

method:MethodNode

the method to be analyzed.

Exceptions
AnalyzerException:
if a problem occurs.
mergeback to summary
private void merge(final int insnIndex, final Frame<V> frame, final Subroutine subroutine) throws AnalyzerException

Merges the given frame and subroutine into the frame and subroutines at the given instruction index. If the frame or the subroutine at the given instruction index changes as a result of this merge, the instruction index is added to the list of instructions to process (if it is not already the case).

Parameters
insnIndex:int

an instruction index.

frame:Frame<V>

a frame. This frame is left unchanged by this method.

subroutine:Subroutine

a subroutine. This subroutine is left unchanged by this method.

Exceptions
AnalyzerException:
if the frames have incompatible sizes.
mergeback to summary
private void merge(final int insnIndex, final Frame<V> frameBeforeJsr, final Frame<V> frameAfterRet, final Subroutine subroutineBeforeJsr, final boolean[] localsUsed) throws AnalyzerException

Merges the given frame and subroutine into the frame and subroutines at the given instruction index (case of a RET instruction). If the frame or the subroutine at the given instruction index changes as a result of this merge, the instruction index is added to the list of instructions to process (if it is not already the case).

Parameters
insnIndex:int

the index of an instruction immediately following a jsr instruction.

frameBeforeJsr:Frame<V>

the execution stack frame before the jsr instruction. This frame is merged into 'frameAfterRet'.

frameAfterRet:Frame<V>

the execution stack frame after a ret instruction of the subroutine. This frame is merged into the frame at 'insnIndex' (after it has itself been merge with 'frameBeforeJsr').

subroutineBeforeJsr:Subroutine

if the jsr is itself part of a subroutine (case of nested subroutine), the subroutine it belongs to.

localsUsed:boolean[]

the local variables read or written in the subroutine.

Exceptions
AnalyzerException:
if the frames have incompatible sizes.
newControlFlowEdgeback to summary
protected void newControlFlowEdge(final int insnIndex, final int successorIndex)

Creates a control flow graph edge. The default implementation of this method does nothing. It can be overridden in order to construct the control flow graph of a method (this method is called by the analyze method during its visit of the method's code).

Parameters
insnIndex:int

an instruction index.

successorIndex:int

index of a successor instruction.

newControlFlowExceptionEdgeback to summary
protected boolean newControlFlowExceptionEdge(final int insnIndex, final int successorIndex)

Creates a control flow graph edge corresponding to an exception handler. The default implementation of this method does nothing. It can be overridden in order to construct the control flow graph of a method (this method is called by the analyze method during its visit of the method's code).

Parameters
insnIndex:int

an instruction index.

successorIndex:int

index of a successor instruction.

Returns:boolean

true if this edge must be considered in the data flow analysis performed by this analyzer, or false otherwise. The default implementation of this method always returns true.

newControlFlowExceptionEdgeback to summary
protected boolean newControlFlowExceptionEdge(final int insnIndex, final TryCatchBlockNode tryCatchBlock)

Creates a control flow graph edge corresponding to an exception handler. The default implementation of this method delegates to newControlFlowExceptionEdge(int, int). It can be overridden in order to construct the control flow graph of a method (this method is called by the analyze method during its visit of the method's code).

Parameters
insnIndex:int

an instruction index.

tryCatchBlock:TryCatchBlockNode

TryCatchBlockNode corresponding to this edge.

Returns:boolean

true if this edge must be considered in the data flow analysis performed by this analyzer, or false otherwise. The default implementation of this method delegates to newControlFlowExceptionEdge(int, int).

newFrameback to summary
protected Frame<V> newFrame(final int numLocals, final int numStack)

Constructs a new frame with the given size.

Parameters
numLocals:int

the maximum number of local variables of the frame.

numStack:int

the maximum stack size of the frame.

Returns:Frame<V>

the created frame.

newFrameback to summary
protected Frame<V> newFrame(final Frame<? extends V> frame)

Constructs a copy of the given frame.

Parameters
frame:Frame<? extends V>

a frame.

Returns:Frame<V>

the created frame.