简体   繁体   中英

Finding Errant Output to System.out in Large Java Program

We have a large java code base [~1 M Lines].

Buried (somewhere) in the code base is some old debug output to System.out that we want to remove (its cluttering things up).

The problem is: out code base is so large that we can't easily find where the output is coming from. What we want is a way to see where System.out.println is getting called from (like a stack trace from an exception or some such).

Its not suitable to debugging -- the errant output is coming from some errant thread somewhere etc.

Any ideas on how to track the source of this errant output down?

PS: 99.99% of calls to System.out are legit, and we have thousands of them, so simply searching the code base for System.out calls is not a solution!

There is a System.setOut() method. If you are really desperate, set this to some wrapper of real stdout and do whatever in your wrapper. Eg compare written string against something and throw if that's the errant output.

With AspectJ, you can easily print the signature for the class that calls System.out.

A simple example that will be adviced by the TraceAspect follows below. The important part is that the class is in the demo package and calls System.out. The aspect will also advice all calls to System.out from all classes in a subpackage of any depth of the demo package.

package demo;

public class DemoClass {

    public void demo() {
        System.out.println("inside demo method..");
    }

    public static void main(String[] args) {
        new DemoClass().demo();
    }
}

To print out the package and class name before the the System.out is called, you can add an Aspect like this:

@Aspect
public class TraceAspect {

    @Pointcut("call(* java.io.PrintStream.*(..))")
    public void sysoutPointcut() {
    }

    @Pointcut("within(demo..*)")
    public void packagePointcut() {
    }

    @Before("sysoutPointcut() && packagePointcut()")
public void beforeSysoutCallInsideDemoPackage(JoinPoint joinPoint) {
    System.out.print(joinPoint.getThis().getClass().getName() + ":"
            + joinPoint.getSourceLocation().getLine() + " - ");
}
}

The output of executing the main method in the DemoClass is:

demo.DemoClass:6 - inside demo method..

With Eclipse and the AspectJ plugin, you can right-click on your project and click Configure --> Convert to AspectJ project. Then the code above will work.

I have written more about AspectJ with @AspectJ style here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM