The "standard" error output stream. This stream is already open and ready to accept output data. Typically this stream corresponds to display output or another output destination specified by the host environment or user. By convention, this output stream is used to display error messages or other information that should come to the immediate attention of a user even if the principal output stream, the value of the variable out, has been redirected to a file or other destination that is typically not continuously monitored.

So, I usually use System.err.println() while debugging (mostly web apps) in my development environment. In most IDEs like Eclipse. System.out and System.err are both print in the same console and since System.err are uniquely highlighted in a different color (red), I find it easier to print out values using System.err as they are visually highlighted and I don't have to go through the whole log to search for my outputs. This always doesn't require me to start my server in debug mode and for cases where I can just determine looking at certain values that I've outputted and not actually break the execution to inspect for states.

Is this a really bad practice, should I not do it? I've been doing this for a long time and I find this very helpful, at times.

  • Print-based debugging is usually OK as a temporary measure for catching a problem quickly. It should be removed from production code. Use proper logging to track the steps your program is taking.
    – 9000
    Apr 30 '15 at 20:10
  • Never in the production code.
    – Yellen
    Apr 30 '15 at 20:11
  • 1
    One problem with printing directly to stderr is that output from parallel threads gets intermingled. Logging fixes that.
    – 9000
    Apr 30 '15 at 20:30
  • 2
    When I think about it more, have you considered setting up an appender that connects to stderr for the local environment?
    – user40980
    Apr 30 '15 at 20:40
  • 2
    I certainly understand... I just happened to have commented out (a few minutes ago) a System.out.println() for local validation. I've also got static analysis tools to check for such and consider it a fatal error to have such a statement in code and fail the build on any fatal error... but yes, I do it too.
    – user40980
    Apr 30 '15 at 20:53

It's not a particularly bad habit to have to want to get output when debugging (the worse habit is to not debug).

Its just that we programmers are just so gosh darn lazy. Want output? Look there...

System.err.println("Got an error: " + e);

That's really easy. You don't need to worry about what logging framework you have, nor what log level it should be at. And this is why we do it all over.

But here's the thing... if you have a project of reasonable size, you have logging in it. If you don't, that's a bad habit. Once you have this logging, and it is something sensible (i.e. not java.util.logging), its really easy to set up an appender that spits out to standard error.

And to this, there's not really an excuse why not to do it that way.

package c.s.p.m.logging;

import org.apache.log4j.Logger;

public class Main {
    private final static Logger LOG = Logger.getLogger(Main.class);

    public static void main(String[] args) {
        LOG.info("This is awkward");
        LOG.error("This is bad");

and (yep, I'm one of those oddballs that uses the xml format - note that this may not be the optimal one)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>

    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.err" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />

    <appender name="file" class="org.apache.log4j.RollingFileAppender">
        <param name="append" value="false" />
        <param name="maxFileSize" value="10MB" />
        <param name="maxBackupIndex" value="10" />
        <param name="file" value="logs/someFile.log" />
        <param name="threshold" value="ERROR" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />

    <logger name="c.s.p.m">
        <level value="DEBUG" />
        <appender-ref ref="console" />

        <level value="ERROR" />
        <appender-ref ref="file" />


and there, in red on my console, I see:

2015-04-30 20:18:34 DEBUG Main:9 - Oops
2015-04-30 20:18:34 INFO  Main:10 - This is awkward
2015-04-30 20:18:34 ERROR Main:11 - This is bad

Meanwhile, in my log file:

2015-04-30 20:18:34 ERROR Main:11 - This is bad

The thing is, there's not really an excuse if you've set it up to just use logging. It's a few more lines in the config file for the console appender.

Once you've got that as a habit to set it up, the logger is much better than System.err ever was and you wonder what took you so long to step away from the println. Time stamps, log levels, line numbers... all for free. You'll find yourself stepping away from that console appender too with a little bit of time. You'll have different log files for different classes (and the aggregate log file too) with a log file watcher. You'll debate putting in crazy appenders...

And best of all, no more silly looks from co-workers because you accidentally checked in a System.err.println() that filled up the console in production.

While System.err.println() isn't bad and isn't a habit that you need to break (as long as you make sure you clean up after yourself and wash your hands afterwards), you will find that once you step away from it there are so many better options out there that are even fewer characters to type.

  • This. Logging gives you more info (e.g. timestamp), is configurable, and should be there anyway. It is so easy, too, as your code example shows. In the end it actually ends up being more concise and simple than typing System.err.println(...);
    – user22815
    May 1 '15 at 15:49

Don't just use the default streams directly. Do you have any simple way of preventing this from happening when you don't actually want to debug your application? Is there any way for you to change the log output target without going over each line and changing it? Are all of the messages you're logging that way actually very serious and require immediate attention in all environments?

You should use a logging framework that abstracts away the actual stream and provides configuration for logging levels.

This way you'll be able to configure just how much information you want. IDEs also allow you to display logs like this in a readable manner and give you filtering capabilities (only showing messages at a certain logging level, text-search, etc.). Just how much support you'll get from an IDE probably depends on the platform you're working on and its specific tooling. For example, LogCat gives you some really nice options for android development. Even if whatever frameworks or servers you're using do not give you this much support, I'd rather get a simple log viewing plugin with colouring and filtering capabilities than use the default stream directly. Or even a standalone tool like BareTail (if you're on Windows). Or even tail -f log_file| grep --line-buffered some_regex_pattern if you're desperate or just want something lightweight and have a Unix terminal.

When managed properly, messages logged by an actual logger can be useful anywhere from development to production.

Just pick log4j, SL4J, Logback or even the classes from java.util.logging

Which one you chose is a wider subject but I find every one of them better than simply using System.err without any layer of abstraction above it.

And for actual debugging, a debugger just works better for me. You don't have to change and recompile the code like you do with those println statements to check the state of variables in scope of the lines being analysed or to inspect a different place. Using it also removes the need for cluttering your code with such statements. They take unnecessary space and, whether you want it or not, you have to visually parse them when trying to understand the logic behind the code.

  • 1
    I've used all the logging frameworks you've mentioned. But sometimes, I just find it easier and faster to just put in a sys.err and I can't directly get a glimpse of what I want to see. This is in IDE, of course, and mostly in developing enterprise web applications/ or sort. And yes, I just do rely on logcat when working on android. This is more of a lazy practice but kind of effective at times. But again, this is not always the case.
    – Yellen
    Apr 30 '15 at 20:32
  • 2
    @Seram you have all the right to do so. I just wanted to give you reasons why I disagree with you. I used to have a very similar opinion on the subject when I was doing programming assignments back at the university but then I changed my mind after colliding with enterprise level code bases using various practices. I don't really see anything effective about using those statements. You can do better even with no IDE and a simple terminal. Seeing a live web-app print megabytes of such statements with no way to limit their number (like in a configurable logger) is a nightmare you don't forget :) Apr 30 '15 at 20:39

I don't think logging is helpful. I think it's a waste of time, since what actually matters, uncaught exceptions, is already printed.

From your quote about System.err:

By convention, this output stream is used to display error messages or other information that should come to the immediate attention of a user even if the principal output stream, the value of the variable out, has been redirected to a file or other destination that is typically not continuously monitored.

Well, we are developers who just want to check some variables while debugging. Those are not errors. That's why I use System.out, which is still readable if you avoid useless output.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.