[EclipseShell-developer] Re: [Jruby-user] EclipseShell: Initial release
Status: Abandoned
Brought to you by:
murphee
From: Werner S. (murphee) <wer...@gm...> - 2006-03-11 16:26:58
|
Lukasz Skowronski wrote: >> >> I thought of ... maybe only setting the System.out to a >> ExecutionEnvironments OutputStream before an execution, >> and then setting it back to the previous one. Of course, if another >> ExecutionEnvironments does the same thing during this execution, >> then all this will be a bit messed up. I'll have to think about this >> some more, and maybe some central manager can take this over. >> > Well, I tried to hack this issue a little. > I played around with custom class loaders in order to load many > instances of the java.lang.System class. > Unfortunatelly custom class loaders cannot define classes which belong > to java package (it's reserved to bootstrap classloader) so I came to > conclusion I cannot have many java.lang.System classes in a JVM. Yup, that's an old issue that's been plaguing some systems that want to run several applications inside one JVM; so, writing a Java Shell that allows you to start several Java programs in the same JVM. > So the situation is clear: there can be only one System and only one > System.out. In my opinion the only way is to replace this global > (accessible from everywhere) PrintStream with a fake PrintStream which > in fact is kind of a manager delegating calls to "real" PrintStreams. > I think you meant something similar when writing about a central manager. Yeah, ... actually, that's an even better idea. Ie. a StdOutManager class derived from PrintStream... EclipseShell sets System.out to this printstream object; Then, whenever an ExecutionEnvironment in EclipseShell starts executing some code, it tells the StdOutManager: "Hey, I'm EE42, please redirect all future System.out.println... to this OutputStream", followed by a "OK, done, stop redirecting" which would cause the StdOutManager to redirect the System.out.println... to the OutputStream it was using before. > Attached you will find a working example - it wasn't trivial so I hope > you'll enjoy it :) Wow, pretty cool... hm... I'm not sure I understand one thing though: Your Threads' run methods call System.setOut(new DispatchingPrintStream(myOut)); 3 consecutive times (because you instantiate 3 threads)... so, basically the first two instances are lost (because they aren't referenced). The reason why this works is that you keep the OutputStreams that keep the Thread's Integer Prefix are stored in a ThreadLocal field, and the currently set DispatchingPrintStream(myOut) just gets this for the current thread and delegates to it. Am I right about that? If I understand this correctly, I have to say, that it's a quite ingenious solution (I wouldn't have thought of it myself). There's only one problem: the ExecutionEnvironments arent' restricted to one Thread per ExecutionEnvironment, ie. whenever I execute a statement, a new Eclipse Job which will execute it (the Eclipse Job system is basically a Worker thread system, that uses a thread pool); so potentially, every code executio will happen in a different thread. Even if I could fix that, then it's still possible that the code executed in the ExecutionEnvironment will create several threads, and their output should go to the same Output Stream. Hmm... although... come to think of it: this should be solved by the fact that you used *Inheritable*ThreadLocal... so all child threads should have the same OutputStream... Other problem: code from an ExecutionEnvironment that gets executed on a different Thread; best example would be code that's called from the UI thread; that's necessary for all GUI modifications in SWT (and Swing), ie. as soon as you change anything in an SWT component, you need to do it on the GUI EventDispatchingThread (using Display.syncExec(Runnable)). Hmm... lots of food for thought... Thanks for that! murphee |