Applications and management of the System.{in,out,err} streams

In a Java application running under (say) Linux, the application is free to do things like changing System.{in,out,err} using the corresponding set methods, or close the corresponding stream objects. These actions will only accect the current application.

If an applicayion running within JNode does these things, it will effect everything else running. This is because the System stream variables, and often the streams themselves, are shared by all running applications. While this behaviour is literally equivalent to what the Sun Java specs say, it is clearly not appropriate:

  • It causes applications to behave differently when run under JNode.
  • It allows one application to "break" another application, and (currently) JNode itself; e.g. by closing System.in.
  • It makes it difficult to implement UNIX-like input stream redirection; e.g from the command shell.

What can we do about this? Clearly saying that applications shouldn't mess with the streams isn't an option ... or that they should get the default io streams from another API ... is not realistic. That means applications would have to be rewritten to run on JNode. And clearly, we cannot change the java.lang.System API. That would also require application code rewrites.

Is there a solution that avoids impacting on Java applications? Maybe. Consider the following.

We cannot remove System.{in,out,err}, or there corresponding set methods. But we could replace the actual input/output/error stream objects with proxy objects that dispatch to (potentially) different streams depending on the application. Then we change the set methods so that they don't change the proxy objects, but change the streams that are dispatched through for the current application.

I think this could be implemented by attaching an InheritedThreadLocal object to each application main thread and using it to hold the application's stream state. This state is used by the proxy streams to decide where to dispatch read/write/etc calls to. The problem of application closes could be handled by the proxy layer simulating the closed stream behaviour itself, and not closing the underlying streams if it is an inappropriate thing to do.

What do people think of this approach?

Isolation

I don't think that it is nececary to implement, because this problem should be fixed when we have isolation support.

Do we have an ETA for

Do we have an ETA for isolate support? Who is working on it? If isolate support is going to be a long time coming, it is worth looking at a interim solution.

Besides, I think that isolates could prove rather expensive for some applications, considering all of the work that creation of an new isolate entails. Consider UNIX where a shell or perl script can fork/exec hundreds of times a second to run other utility commands. Will starting an application in a new isolate be as fast as a typical UNIX fork/exec?

Isolate Speed

There is currently no java application that run hundreds of times an other utility. And I think never hundreds of times an application that change the System in, out or err streams. In JNode it must always be a Java application and the current application don't start other simple java utility in a other JVM because it cost a lot of time to start a new java application. The only reason to implement a proxy is because isolate support can wait on it a long time. So we must know who is working on it and how long it would take.

Chicken and egg

One reason that there is no Java application that runs other applications 100s of times a second is (IMO) that it would be impractically slow! If application launching could be made faster, people would do more of this kind of thing in Java. (Actually, people have tried in the past; c.f. the Echidna system of a few years ago.)

Don't get me wrong. Isolates in JNode will be cool, and will allow us to do stuff that we cannot realistically do otherwise; e.g. killing off applications that have gone bad. But some problems can also be solved in a more light-weight way.