Package org.objectweb.asm.tree.analysis
Class Analyzer<V extends Value>
java.lang.Object
org.objectweb.asm.tree.analysis.Analyzer<V>
- Type Parameters:
V- type of theValueused for the analysis.
- All Implemented Interfaces:
Opcodes
- Direct Known Subclasses:
CheckFrameAnalyzer
A semantic bytecode analyzer. This class does not fully check that JSR and RET instructions
are valid.
-
Field Summary
FieldsModifier and TypeFieldDescription(package private) static final intThe default max memory limit forsetComputeLimits(int, long).(package private) static final longThe default max operations limit forsetComputeLimits(int, long).The execution stack frames of the currently analyzed method (one per instruction index).private List<TryCatchBlockNode>[]The exception handlers of the currently analyzed method (one list per instruction index).private boolean[]The instructions that remain to process (one boolean per instruction index).private InsnListThe instructions of the currently analyzed method.private intThe size ofinsnList.private int[]The indices of the instructions that remain to process in the currently analyzed method.private final Interpreter<V>The interpreter to use to symbolically interpret the bytecode instructions.private ComputeLimitsThe memory and time limits to analyze a method.private intThe maximum number of bytes which can be allocated per analyzed method.private longThe maximum number of "operations" which can be performed per analyzed method.private intThe number of instructions that remain to process in the currently analyzed method.private Subroutine[]The subroutines of the currently analyzed method (one per instruction index).Fields inherited from interface org.objectweb.asm.Opcodes
AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_DEPRECATED, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_MANDATED, ACC_MODULE, ACC_NATIVE, ACC_OPEN, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_RECORD, ACC_STATIC, ACC_STATIC_PHASE, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_TRANSITIVE, ACC_VARARGS, ACC_VOLATILE, ACONST_NULL, ALOAD, ANEWARRAY, ARETURN, ARRAYLENGTH, ASM10_EXPERIMENTAL, ASM4, ASM5, ASM6, ASM7, ASM8, ASM9, ASTORE, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CASTORE, CHECKCAST, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DMUL, DNEG, DOUBLE, DREM, DRETURN, DSTORE, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F_APPEND, F_CHOP, F_FULL, F_NEW, F_SAME, F_SAME1, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAT, FMUL, FNEG, FREM, FRETURN, FSTORE, FSUB, GETFIELD, GETSTATIC, GOTO, H_GETFIELD, H_GETSTATIC, H_INVOKEINTERFACE, H_INVOKESPECIAL, H_INVOKESTATIC, H_INVOKEVIRTUAL, H_NEWINVOKESPECIAL, H_PUTFIELD, H_PUTSTATIC, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILOAD, IMUL, INEG, INSTANCEOF, INTEGER, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISUB, IUSHR, IXOR, JSR, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDIV, LLOAD, LMUL, LNEG, LONG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSUB, LUSHR, LXOR, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, NEW, NEWARRAY, NOP, NULL, POP, POP2, PUTFIELD, PUTSTATIC, RET, RETURN, SALOAD, SASTORE, SIPUSH, SOURCE_DEPRECATED, SOURCE_MASK, SWAP, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_SHORT, TABLESWITCH, TOP, UNINITIALIZED_THIS, V_PREVIEW, V1_1, V1_2, V1_3, V1_4, V1_5, V1_6, V1_7, V1_8, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V9 -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionanalyze(String owner, MethodNode method) Analyzes the given method.analyzeAndComputeMaxs(String owner, MethodNode method) Analyzes the given method and computes and sets its maximum stack size and maximum number of local variables.protected final voidcheckLimits(int numBytes, long numOperations) Checks that the given allocations and operations are within the limits set insetComputeLimits(int, long).computeInitialFrame(String owner, MethodNode method) Computes the initial execution stack frame of the given method.private static intcomputeMaxLocals(MethodNode method) Computes and returns the maximum number of local variables used in the given method.private static intcomputeMaxStack(Frame<?>[] frames) Computes and returns the maximum stack size of a method, given its stack map frames.private voidfindSubroutine(int insnIndex, Subroutine subroutine, List<AbstractInsnNode> 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 insubroutinesfor each encountered instruction.private voidfindSubroutines(int maxLocals) Finds the subroutines of the currently analyzed method and stores them insubroutines.Returns the symbolic execution stack frame for each instruction of the last analyzed method.getHandlers(int insnIndex) Returns the exception handlers for the given instruction.protected voidinit(String owner, MethodNode method) Initializes this analyzer.private voidmerge(int insnIndex, Frame<V> frameBeforeJsr, Frame<V> frameAfterRet, Subroutine subroutineBeforeJsr, boolean[] localsUsed) Merges the given frame and subroutine into the frame and subroutines at the given instruction index (case of a RET instruction).private voidmerge(int insnIndex, Frame<V> frame, Subroutine subroutine) Merges the given frame and subroutine into the frame and subroutines at the given instruction index.protected voidnewControlFlowEdge(int insnIndex, int successorIndex) Creates a control flow graph edge.protected booleannewControlFlowExceptionEdge(int insnIndex, int successorIndex) Creates a control flow graph edge corresponding to an exception handler.protected booleannewControlFlowExceptionEdge(int insnIndex, TryCatchBlockNode tryCatchBlock) Creates a control flow graph edge corresponding to an exception handler.newFrame(int numLocals, int numStack) Constructs a new frame with the given size.Constructs a copy of the given frame.newFrameWithComputeLimits(int numLocals, int numStack) Constructs a new frame with the given size, and subject to the compute limits set insetComputeLimits(int, long).newFrameWithComputeLimits(Frame<? extends V> frame) Constructs a copy of the given frame, and subject to the compute limits set insetComputeLimits(int, long).voidsetComputeLimits(int maxBytes, long maxOperations) Sets the maximum number of bytes which can be allocated, and the maximum number of "operations" which can be performed, to analyze each method.
-
Field Details
-
DEFAULT_MAX_MEMORY_LIMIT
static final int DEFAULT_MAX_MEMORY_LIMITThe default max memory limit forsetComputeLimits(int, long). Update the comment insetComputeLimits(int, long)is you change this value.- See Also:
-
DEFAULT_MAX_OPERATIONS_LIMIT
static final long DEFAULT_MAX_OPERATIONS_LIMITThe default max operations limit forsetComputeLimits(int, long). Update the comment insetComputeLimits(int, long)is you change this value.- See Also:
-
interpreter
The interpreter to use to symbolically interpret the bytecode instructions. -
insnList
The instructions of the currently analyzed method. -
insnListSize
private int insnListSizeThe size ofinsnList. -
handlers
The exception handlers of the currently analyzed method (one list per instruction index). -
frames
The execution stack frames of the currently analyzed method (one per instruction index). -
subroutines
The subroutines of the currently analyzed method (one per instruction index). -
inInstructionsToProcess
private boolean[] inInstructionsToProcessThe instructions that remain to process (one boolean per instruction index). -
instructionsToProcess
private int[] instructionsToProcessThe indices of the instructions that remain to process in the currently analyzed method. -
numInstructionsToProcess
private int numInstructionsToProcessThe number of instructions that remain to process in the currently analyzed method. -
maxBytes
private int maxBytesThe maximum number of bytes which can be allocated per analyzed method. -
maxOperations
private long maxOperationsThe maximum number of "operations" which can be performed per analyzed method. -
limits
The memory and time limits to analyze a method.
-
-
Constructor Details
-
Analyzer
Constructs a newAnalyzer.- Parameters:
interpreter- the interpreter to use to symbolically interpret the bytecode instructions.
-
-
Method Details
-
setComputeLimits
public void setComputeLimits(int maxBytes, long maxOperations) Sets the maximum number of bytes which can be allocated, and the maximum number of "operations" which can be performed, to analyze each method. Operations are not formally defined but their total number is deterministic and approximatively proportional to the computation time.The default limits should be sufficient for any "normal" class. You only need to set new limits if
analyze(java.lang.String, org.objectweb.asm.tree.MethodNode)throws aLimitExceededExceptionon some of your classes.- Parameters:
maxBytes- the maximum number of bytes which can be allocated. Not all object instantiations are tracked (and garbage collection is ignored), but the most important ones are. The default value, 400MB, is more than 20 times larger than the memory used for any method in the java.* modules of the JDK (for theBasicInterpreter,BasicVerifier, andSimpleVerifier; forSourceInterpreter, it is only 4 times larger).maxOperations- the maximum number of "operations" that can be performed. The default value, 50 billions, is more than ten times larger than the number of operations used for any method in the java.* modules of the JDK.
-
analyze
Analyzes the given method.- Parameters:
owner- the internal name of the class to which 'method' belongs (seeType.getInternalName()).method- the method to be analyzed. The maxStack and maxLocals fields must have correct values.- 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).
- Throws:
AnalyzerException- if a problem occurs during the analysis.
-
analyzeAndComputeMaxs
Analyzes the given method and computes and sets its maximum stack size and maximum number of local variables.- Parameters:
owner- the internal name of the class to which 'method' belongs (seeType.getInternalName()).method- the method to be analyzed.- 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).
- Throws:
AnalyzerException- if a problem occurs during the analysis.
-
computeMaxLocals
Computes and returns the maximum number of local variables used in the given method.- Parameters:
method- a method.- Returns:
- the maximum number of local variables used in the given method.
-
computeMaxStack
Computes and returns the maximum stack size of a method, given its stack map frames.- Parameters:
frames- the stack map frames of a method.- Returns:
- the maximum stack size of the given method.
-
findSubroutines
Finds the subroutines of the currently analyzed method and stores them insubroutines.- Parameters:
maxLocals- the maximum number of local variables of the currently analyzed method (long and double values count for two variables).- Throws:
AnalyzerException- if the control flow graph can fall off the end of the code.
-
findSubroutine
private void findSubroutine(int insnIndex, Subroutine subroutine, 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 insubroutinesfor each encountered instruction. Jumps to nested subroutines are not followed: instead, the corresponding instructions are put in the given list.- Parameters:
insnIndex- an instruction index.subroutine- a subroutine.jsrInsns- where the jsr instructions for nested subroutines must be put.- Throws:
AnalyzerException- if the control flow graph can fall off the end of the code.
-
computeInitialFrame
Computes the initial execution stack frame of the given method.- Parameters:
owner- the internal name of the class to which 'method' belongs (seeType.getInternalName()).method- the method to be analyzed.- Returns:
- the initial execution stack frame of the 'method'.
-
getFrames
Returns the symbolic execution stack frame for each instruction of the last analyzed method.- 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.
-
getHandlers
Returns the exception handlers for the given instruction.- Parameters:
insnIndex- the index of an instruction of the last analyzed method.- Returns:
- a list of
TryCatchBlockNodeobjects.
-
init
Initializes this analyzer. This method is called just before the execution of control flow analysis loop inanalyze(java.lang.String, org.objectweb.asm.tree.MethodNode). The default implementation of this method does nothing.- Parameters:
owner- the internal name of the class to which the method belongs (seeType.getInternalName()).method- the method to be analyzed.- Throws:
AnalyzerException- if a problem occurs.
-
newFrame
Constructs a new frame with the given size. Subclasses can override this to construct subclasses ofFrame. But they should not call this method directly, and usenewFrameWithComputeLimits(int, int)instead.- Parameters:
numLocals- the maximum number of local variables of the frame.numStack- the maximum stack size of the frame.- Returns:
- the created frame.
-
newFrame
Constructs a copy of the given frame. Subclasses can override this to construct subclasses ofFrame. But they should not call this method directly, and usenewFrameWithComputeLimits(Frame)instead.- Parameters:
frame- a frame.- Returns:
- the created frame.
-
newFrameWithComputeLimits
Constructs a new frame with the given size, and subject to the compute limits set insetComputeLimits(int, long).- Parameters:
numLocals- the maximum number of local variables of the frame.numStack- the maximum stack size of the frame.- Returns:
- the created frame.
-
newFrameWithComputeLimits
Constructs a copy of the given frame, and subject to the compute limits set insetComputeLimits(int, long).- Parameters:
frame- a frame.- Returns:
- the created frame.
-
newControlFlowEdge
protected void newControlFlowEdge(int insnIndex, 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 theanalyze(java.lang.String, org.objectweb.asm.tree.MethodNode)method during its visit of the method's code).- Parameters:
insnIndex- an instruction index.successorIndex- index of a successor instruction.
-
newControlFlowExceptionEdge
protected boolean newControlFlowExceptionEdge(int insnIndex, 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 theanalyze(java.lang.String, org.objectweb.asm.tree.MethodNode)method during its visit of the method's code).- Parameters:
insnIndex- an instruction index.successorIndex- index of a successor instruction.- 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
Creates a control flow graph edge corresponding to an exception handler. The default implementation of this method delegates tonewControlFlowExceptionEdge(int, int). It can be overridden in order to construct the control flow graph of a method (this method is called by theanalyze(java.lang.String, org.objectweb.asm.tree.MethodNode)method during its visit of the method's code).- Parameters:
insnIndex- an instruction index.tryCatchBlock- TryCatchBlockNode corresponding to this edge.- 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).
-
checkLimits
protected final void checkLimits(int numBytes, long numOperations) Checks that the given allocations and operations are within the limits set insetComputeLimits(int, long). This also checks that the allocations and operations done by the interpreter, since the last call to this method, are within the limits. Subclasses should call this when they allocate additional memory or perform additional operations, for instance ininit(java.lang.String, org.objectweb.asm.tree.MethodNode),newControlFlowEdge(int, int), etc.- Parameters:
numBytes- a number of bytes to allocate.numOperations- a number of operations to perform.- Throws:
LimitExceededException- if the limits are exceeded.
-
merge
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- an instruction index.frame- a frame. This frame is left unchanged by this method.subroutine- a subroutine. This subroutine is left unchanged by this method.- Throws:
AnalyzerException- if the frames have incompatible sizes.
-
merge
private void merge(int insnIndex, Frame<V> frameBeforeJsr, Frame<V> frameAfterRet, Subroutine subroutineBeforeJsr, 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- the index of an instruction immediately following a jsr instruction.frameBeforeJsr- the execution stack frame before the jsr instruction. This frame is merged into 'frameAfterRet'.frameAfterRet- 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- if the jsr is itself part of a subroutine (case of nested subroutine), the subroutine it belongs to.localsUsed- the local variables read or written in the subroutine.- Throws:
AnalyzerException- if the frames have incompatible sizes.
-