Find the location in code of a system.out.println

2019-07-05 00:32发布

问题:

Lets say I'm working in a very large project, and have noticed an empty print line, so I'm assuming there is a System.out.println(""); located somewhere in the code. How would I go about trying to figure out where it is, short of just searching the entire project for all occurrences of System.out.println?

回答1:

You could implement your own PrintStream and use System.setOut to replace the default stdout. Then either put a debugging marker inside the class (if an empty string is printed), or print out the method name through the call stack (throw and catch an exception and get the stack information).



回答2:

If you're using Java 8+, Durian has a StackDumper class which makes it easy to find where a given line is being printed:

StackDumper.dumpWhenSysOutContains("SomeTrigger")

When "SomeTrigger" is printed, this will get dumped to System.err:

+----------\
| Triggered by SomeTrigger
| at package.MyClass.myMethod(MyClass.java:62)
| (the rest of the stacktrace)
+----------/

For your case (looking for an empty string), it's a little more complicated:

PrintStream sysOutClean = System.out;
StringPrinter sysOutReplacement = new StringPrinter(StringPrinter.stringsToLines(line -> {
    if (line.isEmpty()) {
        StackDumper.dump("Found empty line");
    }
    sysOutClean.println(line);
}));
System.setOut(sysOutReplacement.toPrintStream());

Now if there's something like this:

System.out.println("ABC");
System.out.println("123");
System.out.println("");
System.out.println("DEF");

Then your console will look like this:

ABC
123
+----------\
| Found empty line
| at package.MyClass.myMethod(MyClass.java:62)
| (the rest of the stacktrace)
+----------/

DEF


回答3:

This can be due to some of the library also,if you feel that it is because of only System.out.println then,

Solution 1 : Below code snippet should help you to find out the place where it is getting executed.

        import java.io.FileNotFoundException;
        import java.io.PrintStream;

        public class CustomPrintStream extends PrintStream {

        public CustomPrintStream(String fileName) throws FileNotFoundException {
            super(fileName);
        }

            @Override
            public void print(String s) {

                try{
                    if(s == null || s.equals("")){
                        throw new Exception("Invalid print message");
                    }
                    super.print(s);
                }catch(Exception e){
                    //TODO Change to your logger framework and leave it as same 
                    e.printStackTrace();
                }
            }

            public static void main(String[] args) {
                try {
 //TODO : Change to your favorite path and make sure mentioned
//file is available
                    CustomPrintStream customPrintStream = new CustomPrintStream
    ("/home/prem/Desktop/test.log");
                    System.setOut(customPrintStream);
                    System.out.println("");

                } catch (FileNotFoundException e) {
                    //TODO Change to your logger framework and leave it as same 
                    e.printStackTrace();
                }
            }
        }

Solution 2 : Since IDE's are available,please get the help from them.If you are using eclipse Menu -> Search - > File Search-> Place System.out.println(""); in containing search and search for it.

I would rather say not to use the System.out.println in any of the code,for which you can make use of checkstyle and be confident that hence forth no developers use them.



回答4:

Example:

/** Control sysout prints */
public static void main(String[] arg) throws Exception {
     System.out.println("Default"); //print normally

     SysOutController.setSysOutLocationAddressor();
     System.out.println("With Address"); //prints with calling location, and on click location cursor directly focus when System.out.**() called

     SysOutController.ignoreSysout();
     System.out.println("Ignored"); //this line will never prints

     SysOutController.resetSysOut();
     System.out.println("Default"); //print normally as it is (reset)
}

Just call methods of following class, which helps developers to controll sysout

import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

/** 
 * Class which controls System.out prints in console <br/>
 * this class will helps developers to control prints in console
 * @implSpec
 * <pre><code>
 * System.out.println("Default"); //print normally
 * 
 * SysOutController.setSysOutLocationAddressor();
 * System.out.println("With Address"); //prints with calling location
 * 
 * SysOutController.ignoreSysout();
 * System.out.println("Ignored"); //this line will never prints
 * 
 * SysOutController.resetSysOut();
 * System.out.println("Default"); //print normally as it is (reset)
 * </code></pre>
 * @author Dharmendrasinh Chudasama
 */
public class SysOutController {

    private static void setOut(OutputStream out){
        System.setOut(new PrintStream(out));
    }

    private static final OutputStream CONSOLE = new FileOutputStream(FileDescriptor.out);

    /**
     * Reset System.out.print* method
     * @author Dharmendrasinh Chudasama
     */
    public static void resetSysOut() { setOut(CONSOLE); }

    /**
     * System.out.print* will not print anything in console
     * @author Dharmendrasinh Chudasama
     */
    public static void ignoreSysout() {
        setOut(new OutputStream() {
            @Override public void write(int b) throws IOException {}
        });
    }

    /**
     * Address/location of calling System.out.* method will append in console
     * @author Dharmendrasinh Chudasama
     */
    public static void setSysOutLocationAddressor() {
        setOut(new OutputStream() {
            @Override
            public void write(int b) throws IOException {
                if(b=='\n'){ //if newLine
                    final StackTraceElement callerStEl = new Throwable().getStackTrace()[9];
                    String pathData =
                        "\u001B[37m"    //low-visibality
                        + "\t :: ("+callerStEl.getFileName()+":"+callerStEl.getLineNumber()+") ["+callerStEl+"]"  //code path
                        + "\u001B[0m ";  //reset
                    CONSOLE.write(pathData.getBytes());

                }

                CONSOLE.write(b);
            }
        });
    }
}


回答5:

Define a class NewPrintStream extends PrintStream

import java.io.FileNotFoundException;
import java.io.PrintStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NewPrintStream extends PrintStream {
  private static final Logger LOGGER = LoggerFactory.getLogger(NewPrintStream.class);

  public NewPrintStream(String fileName) throws FileNotFoundException {
    super(fileName);
  }

  @Override
  public void println(String x) {
    LOGGER.info("xxxxxxx", new Exception("xxxx"));
  }
}

Then in main class set stdout/stderr print stream

System.setOut(new NewPrintStream("aaa"));
System.setErr(new NewPrintStream("aaa"));