We have a huge (old legacy java) code-base, where many files (around 5k) have System.out.println's. We are planning to remove them for cleanup/performance reasons. How can we write a script that will replace them without introducing any issues in the code? The script cannot blindly delete them as following case can be an issue:
if ()
some.code...
else
System.out.println(...);
DB.close();
I'm thinking of replacing them with ';'. That will take care of above case. Do you see any other issues? Any other suggestions?
Have you consider the silly case:
I don't think it happen but chances are the println executes a method that is actually performing some action on which the system depends on and may introduce subtle bugs ( believe me or not, but I have witnessed this )
Probably replacing with a logger and disabling the loggers may do.
Or creating a null object using the NullObject pattern:
And replacing
With
Log4E is an eclipse plugin that has a "Replace System.out.println()" feature. It will happily convert all those pesky println calls to log4j calls. It will even wrap them with a log level check.
Have you considered editing those source files to remove the lines?
You might find that it will only a developer a couple of days to go through and get rid of most of them. We had a similar issue and I just got up really early and went through all our files getting rid of rubbish.
I used Eclipse and the clean up on save feature to cleanup imports and stuff at the same time.
Its quite a therapeutic thing to do!
You could start by calling Systems.setOut and passing in your own OutputStream that does nothing. That will help you see if there is a perfomance gain. This is safer than removing them (for the reason that Oscar pointed out - coding by side effect). If the performance gain is negligable then you might want to focus your efforts elsewhere.
Two issues with my above method:
However it is a good quick test to see if you get the performance gains you are looking for.
You could use a conditional compilation to have a debug build with the print statements and a release build without them.
Basically, the idea is to create a final static class with a final static boolean that you use as a switch at compile time.
Then you can just replace all of your
System.out.println
statements withSince the compiler will ignore any unreachable branches of code, you can just set
ON = false
when you do a release build and the print statements will be excluded from your bytecode.Note: This doesn't deal with the case that Oscar pointed out, where a print statement may change the state of some object. You could use conditional compilation to print to a null object when in release mode, as he suggested, instead of removing the prints altogether.
I wrote a regex in perl that replaces the string "System.out.println" with ";//System.out.println". I believe that there are very few cases where this would break the build. It would just become an "else ;", which is compiled to zero bytecode instructions.
It looks like this is what you've proposed. It worked for me -- except if you have additional statements on the same line. However, that is bad style to begin with (and I knew I didn't do that).