Log4j doesn't allow to catch stdout and stderr messages out of the box. However, you can still intercept them
with a custom output stream, which is especially useful when you have to log data that third-party libraries write to
the standard streams.
This has already been done by Jim Moore (have a look at the LoggingOutputStream in the log4j source code). The issue
is that this LoggingOutputStream requires org.apache.log4j.Category and org.apache.log4j.Priority which are now
partially deprecated.
Here is a modified LoggingOutputStream that avoids deprecated methods:
publicclassLoggingOutputStreamextendsOutputStream{/** * Default number of bytes in the buffer. */privatestaticfinalintDEFAULT_BUFFER_LENGTH=2048;/** * Indicates stream state. */privatebooleanhasBeenClosed=false;/** * Internal buffer where data is stored. */privatebyte[]buf;/** * The number of valid bytes in the buffer. */privateintcount;/** * Remembers the size of the buffer. */privateintcurBufLength;/** * The logger to write to. */privateLoggerlog;/** * The log level. */privateLevellevel;/** * Creates the Logging instance to flush to the given logger. * * @param log the Logger to write to * @param level the log level * @throws IllegalArgumentException in case if one of arguments is null. */publicLoggingOutputStream(finalLoggerlog,finalLevellevel)throwsIllegalArgumentException{if(log==null||level==null){thrownewIllegalArgumentException("Logger or log level must be not null");}this.log=log;this.level=level;curBufLength=DEFAULT_BUFFER_LENGTH;buf=newbyte[curBufLength];count=0;}/** * Writes the specified byte to this output stream. * * @param b the byte to write * @throws IOException if an I/O error occurs. */publicvoidwrite(finalintb)throwsIOException{if(hasBeenClosed){thrownewIOException("The stream has been closed.");}// don't log nullsif(b==0){return;}// would this be writing past the buffer?if(count==curBufLength){// grow the bufferfinalintnewBufLength=curBufLength+DEFAULT_BUFFER_LENGTH;finalbyte[]newBuf=newbyte[newBufLength];System.arraycopy(buf,0,newBuf,0,curBufLength);buf=newBuf;curBufLength=newBufLength;}buf[count]=(byte)b;count++;}/** * Flushes this output stream and forces any buffered output * bytes to be written out. */publicvoidflush(){if(count==0){return;}finalbyte[]bytes=newbyte[count];System.arraycopy(buf,0,bytes,0,count);Stringstr=newString(bytes);log.log(level,str);count=0;}/** * Closes this output stream and releases any system resources * associated with this stream. */publicvoidclose(){flush();hasBeenClosed=true;}}
Now you can intercept and log messages that are flushed to stderr or stdout: