/**
   * overrides the visitor to initialize and tear down the opcode stack
   *
   * @param classContext the context object of the currently parsed class
   */
  @Override
  public void visitClassContext(ClassContext classContext) {
    try {
      String clsName = classContext.getJavaClass().getClassName();
      isInnerClass = clsName.contains("$");

      clsSignature = SignatureUtils.classToSignature(clsName);
      stack = new OpcodeStack();
      localSpecialObjects = new HashMap<>();
      fieldSpecialObjects = new HashMap<>();
      super.visitClassContext(classContext);

      if (!isInnerClass && !fieldSpecialObjects.isEmpty()) {

        for (Map.Entry<String, String> entry : fieldSpecialObjects.entrySet()) {
          String fieldName = entry.getKey();
          String signature = entry.getValue();
          bugReporter.reportBug(
              makeFieldBugInstance().addClass(this).addField(clsName, fieldName, signature, false));
        }
      }
    } finally {
      stack = null;
      localSpecialObjects = null;
      fieldSpecialObjects = null;
    }
  }
 /**
  * Checks to see if any of the locals or fields that we are tracking are passed into another
  * method. If they are, we clear out our tracking of them, because we can't easily track their
  * progress into the method.
  *
  * <p>This can be overridden to check for exceptions to this rule, for example, being logged to
  * the console not counting.
  */
 protected void processMethodParms() {
   String sig = getSigConstantOperand();
   int numParms = SignatureUtils.getNumParameters(sig);
   if ((numParms > 0) && (stack.getStackDepth() >= numParms)) {
     for (int i = 0; i < numParms; i++) {
       clearUserValue(stack.getStackItem(i));
     }
   }
 }
 private void sawInvokeInterfaceVirtual() {
   String sig = getSigConstantOperand();
   int numParms = SignatureUtils.getNumParameters(sig);
   if (stack.getStackDepth() > numParms) {
     OpcodeStack.Item item = stack.getStackItem(numParms);
     Object uo = item.getUserValue();
     if (uo != null) {
       String name = getNameConstantOperand();
       if (isMethodThatShouldBeCalled(name)) {
         clearUserValue(item);
       } else if (!"clone".equals(name)) {
         if ((!Values.SIG_VOID.equals(SignatureUtils.getReturnSignature(sig))) && !nextOpIsPop()) {
           clearUserValue(item);
         }
       }
     }
   }
   processMethodParms();
 }
 @Override
 public void visitField(Field obj) {
   if (!isInnerClass && obj.isPrivate() && !obj.isSynthetic()) {
     String sig = obj.getSignature();
     if (sig.startsWith(Values.SIG_QUALIFIED_CLASS_PREFIX)) {
       String type = SignatureUtils.stripSignature(sig);
       if (doesObjectNeedToBeWatched(type)) {
         fieldSpecialObjects.put(obj.getName(), obj.getSignature());
       }
     }
   }
 }