本文介绍了编写检测器以搜索“ System.out.println”的使用。使用Findbugs的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个错误检测器,以使用Findbugs查找方法调用 System.out.println的实例。

I am trying to write a bug detector to find instances of the method call "System.out.println" using Findbugs.

我知道字节码中的 System.out.println被编译为对GETSTATIC的调用,。调用INVOKEVIRTUAL会将 System.out弹出堆栈并调用该方法。

I understand that "System.out.println" in bytecode is compiled to a call to GETSTATIC, which pushes "System.out" onto the stack. A call to INVOKEVIRTUAL pops "System.out" off the stack and calls the method.

我准备了一些代码(如下所示),可以找到正确的GETSTATIC和INVOKEVIRTUAL调用,但是无法将两者链接在一起。我怀疑我可能需要以某种方式使用OpcodeStack,但是在理解如何使用它方面遇到了麻烦。任何帮助,将不胜感激。

I have prepared some code (found below) which finds the correct GETSTATIC and INVOKEVIRTUAL calls, but have been unable to link the two together. I suspect I may need to use OpcodeStack in some way, but am having trouble in understanding how I can use it. Any help would be appreciated.

    @Override
    public void sawOpcode(int seen) {
            // if opcode is getstatic
            if (seen == GETSTATIC) {
                    String clsName = getClassConstantOperand();
                    if ("java/lang/System".equals(clsName)) {
                            String fldName = getNameConstantOperand();
                            if ("out".equals(fldName)) {
                                    System.out.println("SYSTEM.OUT here");
                            }
                    }
            }

            // if opcode is invokevirtual
            if (seen == INVOKEVIRTUAL) {
                    String cls = getDottedClassConstantOperand();
                    if ("java.io.PrintStream".equals(cls)) {
                            String methodName = getNameConstantOperand();
                            if ("println".equals(methodName)) {
                                    bugReporter.reportBug(new BugInstance("SYSTEM_OUT_PRINTLN",
                                                    NORMAL_PRIORITY).addClassAndMethod(this)
                                                    .addSourceLine(this));
                            }
                    }
            }

    }


推荐答案

我发现,对于我的用例来说,足以确定完全使用了System.out或System.err -在99%在某些情况下,这些将用于稍后在代码块中调用.print或.println。我的检测器检测到加载System.err或System.out的GET_STATIC操作码。下面的代码显示了确定发生这种情况的3种选择。

I found that, for my use case, it is enough to determine that System.out or System.err are used at all - in 99% of cases, these will be used for calling .print or .println later in the block. My detector detects GET_STATIC opcodes that load System.err or System.out. The code is below, showing 3 alternatives of determining that this occurs.

package my.findbugs.detectors.forbiddencalls;

import org.apache.log4j.Logger; // it is not trivial to use a logger with FindBugs in Eclipse, leave it out if there are problems

import my.findbugs.detectors.util.DetectorUtil;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.classfile.FieldDescriptor;


public class CallToSystemOutPrintlnDetector2 extends OpcodeStackDetector {

    private static final Logger LOGGER = Logger.getLogger(CallToSystemOutPrintlnDetector2.class);
    private BugReporter bugReporter;


    public CallToSystemOutPrintlnDetector2(BugReporter bugReporter) {
        super();
        this.bugReporter = bugReporter;
        LOGGER.debug("Instantiated.");
    }


    public void sawOpcode(int seen) {

        // find occurrences of:
        //2:   getstatic       #54; //Field java/lang/System.out:Ljava/io/PrintStream;
//2:   getstatic       #54; //Field java/lang/System.out:Ljava/io/PrintStream;

        if (seen == GETSTATIC){

            try {
//              LOGGER.debug(operand); // static java.lang.System.out Ljava/io/PrintStream;
//              LOGGER.debug(operand.getClass()); // class edu.umd.cs.findbugs.classfile.analysis.FieldInfo
//              LOGGER.debug(operand.getName()); // err
//              LOGGER.debug(operand.getClassDescriptor()); // java/lang/System
//              LOGGER.debug(operand.getSignature()); // Ljava/io/PrintStream;

                FieldDescriptor operand = getFieldDescriptorOperand();
                ClassDescriptor classDescriptor = operand.getClassDescriptor();
                if ("java/lang/System".equals(classDescriptor.getClassName()) &&
                        ("err".equals(operand.getName())||"out".equals(operand.getName()))) {
                    reportBug();
                }
            } catch (Exception e) {
                //ignore
            }

            // could be used
//          try {
//              MethodDescriptor operand = getMethodDescriptorOperand();
//              LOGGER.debug(operand); // java.lang.System.outLjava/io/PrintStream;
//              LOGGER.debug(operand.getClass()); // class edu.umd.cs.findbugs.classfile.MethodDescriptor
//              LOGGER.debug(operand.getName()); // err
//              LOGGER.debug(operand.getClassDescriptor()); // java/lang/System
//              LOGGER.debug(operand.getSignature()); // Ljava/io/PrintStream;
//          } catch (Exception e) {
//              //ignore
//          }

            // could be used
//          try {
//              String operand = getRefConstantOperand();
//              LOGGER.debug(operand); // java.lang.System.out : Ljava.io.PrintStream;
//              if (operand != null && (
//                  operand.startsWith("java.lang.System.out :") || operand.startsWith("java.lang.System.err :"))) {
//                  reportBug();
//              }
//          } catch (Exception e) {
//              //ignore
//          }
        }
    }

    private void reportBug(){
        this.bugReporter.reportBug(getBugInstance());
    }


    private BugInstance getBugInstance() {
        return new BugInstance(this, "MY_CALL_TO_SYSTEM_OUT_BUG", DetectorUtil.MY_PRIORITY)
            .addClassAndMethod(this)
            .addSourceLine(this);
    }

}

这篇关于编写检测器以搜索“ System.out.println”的使用。使用Findbugs的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 16:30