views:

38

answers:

2

Hi,

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!

+5  A: 

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. E.g. compare written string against something and throw if that's the errant output.

doublep
I think this is exactly correct. Make your own stream and when the offending message comes through. Just print a stack trace:new RuntimeException().printStackTrace();
Tim Perry
Great answer! It doesn't require real desperation - I think it could be completed in a few minutes.
Skip Head
+2  A: 

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.

Espen