views:

239

answers:

6

Could there be any obvious reason why a Java program I run from the Eclipse IDE's output is different from what I get if I do the same with the command line in Windows (XP)? I am using the JDK 1.6.0_04 and Eclipse 3.4.0

The program creates threads and then tests a locking algorithm. In Eclipse, the threads do not interfere with each other. However, using javac, the threads interrupt each other.

+2  A: 

If you're playing with threads, the console output could vary wildly from machine to machine, and I'm sure eclipse does something to affect threading in some way.

Stefan Kendall
+2  A: 

One thing that might be the cause of different behaviour is, if you have ie. two jars that provide the same functionality (ie. two versions of the same jar). Depending on how you specify the classpath the code from one jar can override the other.

Now in eclipse the order might just be different than on commandline - thus you actually call different code which results in different output.

Niko
Keeping Eclipse's generated classpath information seems to be the way to go.
pypmannetjies
+1  A: 

I was under the impression that Eclipse has its own built-in compiler (and a Google search confirms I'm right). There may be minor differences in how it compiles versus javac.

Barry Kelly
A: 

Yes, perhaps Eclipse has enabled a JAVA option like verbose garbage collection or something. You can usually connect to the JVM using [jre]/bin/Jconsole.exe to see what is enabled on the JVM and then you could compare. This will show you differences in classpath as well as other things. To make that work you need to add this as a startup option to the jvm that you want to inspect:
-Dcom.sun.management.jmxremote

djangofan
A: 

Are you sure you synchronized the threads properly, where necessary?

Are the threads dependent on each other? If so, this is a likely reason for the difference in behaviour.

Try to analyze your program. Would the program work if thread 1 finishes way quicker than thread 2? Would the program work if thread 2 finishes way quicker than thread 1?

If for example thread 1 generates a result which will later be used by thread 2. Is there any guarantee that thread 2 does not try to use that result before it is generated? (lets say that thread 2 runs really fast)

In summary: Different relative execution times might be the reason for the difference in behaviour, if the program is badly synchronized

Alderath
A: 

I assume that you say the "threads interrupt each other" you mean that the output from the two threads is interspersed. I also imagine that you are writing to System.err or System.out.

I believe what you are seeing is a consequence of two threads doing unsynchronized output to the same stream. In Eclipse, the stream you are writing to has sufficient buffering that a call to write() will not stall (99.9% of the time). By contrast, when you run from the command line, it is quite possible that each Java write() call is resulting in a write system call, stalling one thread and scheduling the other one. Indeed, it is even possible that a Java write() may turn into multiple write system calls!

The simple answer would be to try and change the buffering for your stream. Unfortunately, I don't think that the Java APIs allow you to do this for the console standard output/error streams.

Other imperfect answers include:

  • Change your application to synchronize all of your writes on the System.out/err object. Unfortunately, this is liable to mask synchronization bugs in the code you are trying to test!!

  • Change your application to output to a ByteArrayOutputStream(). This will reduce the change of "interruption", but it could still occasionally happen, unless you synchronize.

The best answer I can think of is to create a wrapper Stream / Reader class that synchronizes writes to a ByteArrayOutputStream, write all the messages to an instance, then dump the lot to System.out (or wherever) when the test is done. This could mask synchronization bugs, but it is far less likely than if you synchronized on the System.out/err objects.

Stephen C