Thread: [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 |
From: Lukasz S. <har...@op...> - 2006-03-15 00:11:39
|
----- Original Message ----- From: "Werner Schuster (murphee)" <wer...@gm...> To: <ecl...@li...> Sent: Saturday, March 11, 2006 5:26 PM (1) > 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. (2) > 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... murphee, do you agree that two problems above are quite easy to solve as I wrote in a mail to you? (1) - I mean associating given console with some information from the ExecutionEnvironment context (e.g. editor name). (2) - InheritableThreadLocal in fact solves problem with child threads. > 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)). > This seems to be unsolvable in general - it will be very difficult (maybe even impossible) to mess with e.g. EventQueue.invokeLater(Runnable) - because it's in java.* hierarchy and cannot be loaded by class loader other than bootstrap class loader. Hence we can't modify it's bytecode. We could try to apply some aspects on code which calls the EventQueue methods. If we have source code with calls to these methods then weaving shall be quite straightforward - I'm not sure what would be in case of weaving aspects into bytecode (when we don't have the sources) - would this capture properly all invokations or not. On the other side - if the class being called wouldn't be in java hierarchy (let it be javax.swing.SwingUtilities instead) then we can try to add an aspect to it which would be able to match Runnable classloader to the proper console. Of course each Runnable instance would be created by custom classloader - we have to ensure that each ExecutionEnvironment will have its own classloader to load Runnable class. Then we could take this classloader in weaved invokeLater method, find the ExecutionEnvironment and then the actual console. When I'll have a little time I'll try to play with aspects.. And of course - when we send a Runnable to another thread (not created by us) the call stack is unusable for our purposes.. No info about caller is supplied there... Regards, Lukasz |
From: Lukasz S. <har...@op...> - 2006-03-28 21:01:29
|
----- Original Message ----- From: "Lukasz Skowronski" <har...@op...> To: <ecl...@li...> Sent: Wednesday, March 15, 2006 2:10 AM Subject: [EclipseShell-developer] stdout discussion continued > > ----- Original Message ----- > From: "Werner Schuster (murphee)" <wer...@gm...> > To: <ecl...@li...> > Sent: Saturday, March 11, 2006 5:26 PM > > > > 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)). > > > > This seems to be unsolvable in general - it will be very difficult (maybe > even impossible) to mess with e.g. EventQueue.invokeLater(Runnable) - > because it's in java.* hierarchy and cannot be loaded by class loader other > than bootstrap class loader. Hence we can't modify it's bytecode. > We could try to apply some aspects on code which calls the EventQueue > methods. If we have source code with calls to these methods then weaving > shall be quite straightforward - I'm not sure what would be in case of > weaving aspects into bytecode (when we don't have the sources) - would this > capture properly all invokations or not. > > On the other side - if the class being called wouldn't be in java hierarchy > (let it be javax.swing.SwingUtilities instead) then we can try to add an > aspect to it which would be able to match Runnable classloader to the proper > console. Of course each Runnable instance would be created by custom > classloader - we have to ensure that each ExecutionEnvironment will have its > own classloader to load Runnable class. Then we could take this classloader > in weaved invokeLater method, find the ExecutionEnvironment and then the > actual console. > > When I'll have a little time I'll try to play with aspects.. > After playing a little with AspectWerkz and AspectJ I believe that what I wrote above is all true. There is no easy way to modify classes from java.* hierarchy - there are legal issues (because of the Sun license) and it requires mungling with bootstrap classloader. Anyway modyfing java.* classes in the Eclipse environment is not the best idea I think. Well Murphee, what about integrating my idea of a fake PrintStream into the EclipseShell? I can prepare and send you the appriopriate code. Regards, Lukasz |