Class Analyzer<V extends Value>

java.lang.Object
org.objectweb.asm.tree.analysis.Analyzer<V>
Type Parameters:
V - type of the Value used for the analysis.
All Implemented Interfaces:
Opcodes
Direct Known Subclasses:
CheckFrameAnalyzer

public class Analyzer<V extends Value> extends Object implements Opcodes
A semantic bytecode analyzer. This class does not fully check that JSR and RET instructions are valid.
  • Field Details

    • interpreter

      private final Interpreter<V extends Value> interpreter
      The interpreter to use to symbolically interpret the bytecode instructions.
    • insnList

      private InsnList insnList
      The instructions of the currently analyzed method.
    • insnListSize

      private int insnListSize
      The size of insnList.
    • handlers

      private List<TryCatchBlockNode>[] handlers
      The exception handlers of the currently analyzed method (one list per instruction index).
    • frames

      private Frame<V extends Value>[] frames
      The execution stack frames of the currently analyzed method (one per instruction index).
    • subroutines

      private Subroutine[] subroutines
      The subroutines of the currently analyzed method (one per instruction index).
    • inInstructionsToProcess

      private boolean[] inInstructionsToProcess
      The instructions that remain to process (one boolean per instruction index).
    • instructionsToProcess

      private int[] instructionsToProcess
      The indices of the instructions that remain to process in the currently analyzed method.
    • numInstructionsToProcess

      private int numInstructionsToProcess
      The number of instructions that remain to process in the currently analyzed method.
  • Constructor Details

    • Analyzer

      public Analyzer(Interpreter<V> interpreter)
      Constructs a new Analyzer.
      Parameters:
      interpreter - the interpreter to use to symbolically interpret the bytecode instructions.
  • Method Details

    • analyze

      public Frame<V>[] analyze(String owner, MethodNode method) throws AnalyzerException
      Analyzes the given method.
      Parameters:
      owner - the internal name of the class to which 'method' belongs (see Type.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

      public Frame<V>[] analyzeAndComputeMaxs(String owner, MethodNode method) throws AnalyzerException
      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 (see Type.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

      private static int computeMaxLocals(MethodNode method)
      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

      private static int computeMaxStack(Frame<?>[] frames)
      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

      private void findSubroutines(int maxLocals) throws AnalyzerException
      Finds the subroutines of the currently analyzed method and stores them in subroutines.
      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 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 - 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

      private Frame<V> computeInitialFrame(String owner, MethodNode method)
      Computes the initial execution stack frame of the given method.
      Parameters:
      owner - the internal name of the class to which 'method' belongs (see Type.getInternalName()).
      method - the method to be analyzed.
      Returns:
      the initial execution stack frame of the 'method'.
    • getFrames

      public Frame<V>[] 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

      public List<TryCatchBlockNode> getHandlers(int insnIndex)
      Returns the exception handlers for the given instruction.
      Parameters:
      insnIndex - the index of an instruction of the last analyzed method.
      Returns:
      a list of TryCatchBlockNode objects.
    • init

      protected void init(String owner, MethodNode method) throws AnalyzerException
      Initializes this analyzer. This method is called just before the execution of control flow analysis loop in analyze(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 (see Type.getInternalName()).
      method - the method to be analyzed.
      Throws:
      AnalyzerException - if a problem occurs.
    • newFrame

      protected Frame<V> newFrame(int numLocals, int numStack)
      Constructs a new frame with the given size.
      Parameters:
      numLocals - the maximum number of local variables of the frame.
      numStack - the maximum stack size of the frame.
      Returns:
      the created frame.
    • newFrame

      protected Frame<V> newFrame(Frame<? extends V> frame)
      Constructs a copy of the given frame.
      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 the analyze(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 the analyze(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

      protected boolean newControlFlowExceptionEdge(int insnIndex, 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(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).
    • merge

      private void merge(int insnIndex, Frame<V> frame, 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 - 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.