Find the location in the system.out.println code
Suppose I am working on a very large project and noticed an empty print line, so I am assuming System.out.println (""); somewhere in the code. How do I try to figure out where it is and not just search the whole project for all occurrences of System.out.println?
You can implement your own PrintStream
and use System.setOut
stdout to replace the standard output. Then either put a debug marker inside the class (if an empty string is printed) or print the method name across the call stack (throw and catch the exception and get stack info).
If you're using Java 8+, Durian has a StackDumper , making it easy to find where a given string is being printed:
StackDumper.dumpWhenSysOutContains("SomeTrigger")
When "SomeTrigger" is printed, this will reset to System.err
:
+----------\
| Triggered by SomeTrigger
| at package.MyClass.myMethod(MyClass.java:62)
| (the rest of the stacktrace)
+----------/
In your case (searching for an empty string) this is 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 is 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
It may be related to some of the library, if you feel like it is due to System.out.println only then
Solution 1: Below code snippet will help you find out where it is running.
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 IDEs are available, please contact them for help. If you are using eclipse Menu -> Search -> Find Files -> Place System.out.println (""); in search and search.
I would rather not use System.out.println in any of the code you can use checkstyle for, and be sure that therefore no developer is using them.
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 the following class which helps developers to control 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);
}
});
}
}
Define 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 the main class set the output stream to stdout / stderr
System.setOut(new NewPrintStream("aaa"));
System.setErr(new NewPrintStream("aaa"));