How to remove System.out.println's from codeba

2019-01-23 07:09发布

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?

8条回答
该账号已被封号
2楼-- · 2019-01-23 07:37

Have you consider the silly case:

System.out.println(" Print " +  object.changeState() );

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:

public final class DevNull { 
    public final static PrintStream out = new PrintStream(new OutputStream() {
        public void close() {}
        public void flush() {}
        public void write(byte[] b) {}
        public void write(byte[] b, int off, int len) {}
        public void write(int b) {}

    } );
}

And replacing

 System.out.println();

With

 DevNull.out.println();
查看更多
来,给爷笑一个
3楼-- · 2019-01-23 07:43

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.

查看更多
可以哭但决不认输i
4楼-- · 2019-01-23 07:45

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!

查看更多
Lonely孤独者°
5楼-- · 2019-01-23 07:58

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:

  1. any System.out.printlns you want to keep will disapper too
  2. the String concatination will still take place (and that can be expensive depending on how much there is)

However it is a good quick test to see if you get the performance gains you are looking for.

查看更多
Evening l夕情丶
6楼-- · 2019-01-23 07:58

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.

public final class Debug {
   //set to false to allow compiler to identify and eliminate
   //unreachable code
   public static final boolean ON = true;
}

Then you can just replace all of your System.out.println statements with

if(Debug.ON)
{
    System.out.println...
}

Since 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.

查看更多
贼婆χ
7楼-- · 2019-01-23 07:58

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).

查看更多
登录 后发表回答