I have an application that combines all its logging into one instance of a class to facilitate selective printing of debugging, etc. The class works for about a year or so, it works smoothly, but most recently I had to flip the log level to the highest value (which I rarely do), and the standard output seems to eventually block . This crashes the next time some other part of the code calls println , or when it tries to use the logging class (which is blocked waiting for println return).
My first thought was that I had some kind of concurrency problem with my logging class, but clearing the stack trace assures me that my synchronization is working correctly and that only one thread is trying to write to the console at any given time. Here is an example stack trace on an abusive thread:
Thread [Thread-127] (Suspended) FileOutputStream.writeBytes(byte[], int, int) line: not available [native method] [local variables unavailable] FileOutputStream.write(byte[], int, int) line: 260 BufferedOutputStream.flushBuffer() line: 65 BufferedOutputStream.flush() line: 123 PrintStream.write(byte[], int, int) line: 432 StreamEncoder.writeBytes() line: 202 StreamEncoder.implFlushBuffer() line: 272 StreamEncoder.flushBuffer() line: 85 OutputStreamWriter.flushBuffer() line: 168 PrintStream.write(String) line: 477 PrintStream.print(String) line: 619 PrintStream.println(String) line: 756 Logger(Logger).LogMessage(String) line: 180 RemoteConsoleMonitor$1.run() line: 56 Thread.run() line: 662
Digging a little deeper into my own stack traces, I found that the JVM process blocks its own ZwWriteFile call to Windows. My best guess is that the JVM uses named pipes configured to read / write buffered data synchronously, but something stops somehow and allows the buffer to fill up. Meanwhile, the writer is blocked, waiting for the buffer space to become available, but this will never happen. Here's a full-stack trace of the same thread:
ntdll.dll!_ZwWriteFile@36 () + 0x15 bytes ntdll.dll!_ZwWriteFile@36 () + 0x15 bytes jvm.dll!InterfaceSupport::serialize_memory(JavaThread * thread=0x00000220) Line 40 + 0x9 bytes C++ java.dll!writeBytes(const JNINativeInterface_ * * env=0x2ac2b13c, _jobject * this=0x3e00f204, _jobject * bytes=0x3e00f200, long off=0, long len=97, _jfieldID * fid=0x7ecee033) Line 144 + 0x21 bytes C java.dll!Java_java_io_FileOutputStream_writeBytes(const JNINativeInterface_ * * env=0x2ac2b13c, _jobject * this=0x3e00f204, _jobject * bytes=0x3e00f200, long off=0, long len=97) Line 73 + 0x20 bytes C 0d8a3826() ...
The end result is that the stdout buffer fills up and sooner or later the material stops writing to the console.
Here's the catch: if I run the application offline instead of launching it from the Apache Ant build script, I cannot reproduce the problem. Thus, this may be due to the way Ant redirects the output of the process, but I hesitate to send an error report because it seems that someone else has encountered this problem before ... and because I cannot get the same behavior is reproduced in isolation.
Any thoughts or tips on how I can track this further?
UPDATE . Updating Eclipse from 3.4.2 to Helios (M2) magically resolved the issue. I can also continue to use 3.4.2 by running the integrated Ant constructor from the command line instead of the user interface:
java -jar <eclipse directory>\plugins\org.eclipse.equinox.launcher_<version>.jar -application org.eclipse.ant.core.antRunner -buildfile <buildfile>