A cute hack: Changing the scope of System.out

This isn’t any sort of deep trick. I just found the results surprisingly pleasant, so thought I’d share.

In the GUI interpreter I need to be able to capture standard out. Doing println in the interpreter should print to the screen, not the console. And that’s fine. Java provides System.setOut. I had to fight the stupidities of java.io a bit to make it work (annoying details with flushing among other things), but it did in the end.

There is of course a problem with this. System.out is basically a great honking big global variable. We’ve now made it impossible to run multiple interpreters in the same VM. Le sigh.

Ok. So, what we do is a bit of juggling and set System.out appropriately before interpreting each thing. Right?

Nope. Doesn’t work. These things can and do live in separate threads. And for that matter, what about background threads spawned by one of the interpreters?

The solution is to make System.out thread local. And not just any type of thread local – an inheritable thread local. Spawned threads need to inherit the System.out of their parent thread so that something like spawn { println(“Hello world”) } prints to the right screen.

Once you have this, the idea is obvious. You define an object which extends OutputStream but delegates all functionality to some thread local variable (snarfing the System.out that was present when the object loads as the default value), set System.out to be a print stream wrapping that and you’re done. You can now set its value in a thread local way and multiple interpreters can coexist peacefully.

Like I said, nothing special, but it seems like a surprisingly handy trick.

This entry was posted in programming and tagged , , , on by .

5 thoughts on “A cute hack: Changing the scope of System.out

  1. Madoc

    I don’t quite understand this. If You spawn a new process in Java, You can very well capture/override the standard input, output and error streams for that process only.

  2. david Post author

    Of course you can. But who said anything about spawning processes? I need these things running in the same VM.

    This is about redirecting the standard output for a specific thread.

  3. Bas de Bakker

    Nice, but unfortunately a PrintStream isn’t thread safe. It has a “trouble” flag that is set when the underlying stream throws an IOException. So to get this right you’d need to subclass PrintStream and override all its methods to forward to a thread local variable.

Comments are closed.