Tôi hiện đang gỡ lỗi một chương trình có hai luồng cho mỗi quy trình bên ngoài và hai luồng đó tiếp tục đọc Process.getErrorStream() và Process.getInputStream() sử dụng vòng lặp while ((i = in.read(buf, 0, buf.length)) >= 0)
.Sử dụng CPU 100% vô hạn tại java.io.FileInputStream.readBytes (Phương thức gốc)
Đôi khi khi quá trình bên ngoài gặp sự cố do lỗi JVM (xem these hs_err_pid.log files), các chuỗi đọc stdout/stderr của quá trình bên ngoài đó bắt đầu tiêu thụ CPU 100% và không bao giờ thoát. Cơ thể vòng lặp không được thực thi (Tôi đã thêm tuyên bố ghi nhật ký ở đó), do đó vòng lặp vô hạn dường như nằm trong phương thức gốc java.io.FileInputStream.readBytes
.
Tôi đã sao chép điều này trên cả Windows 7 64 bit (jdk1.6.0_30 64 bit, jdk1.7.0_03 64 bit) và Linux 2.6.18 (jdk1.6.0_21 32 bit). Mã được đề cập là here và mã được sử dụng like this. Xem các liên kết cho mã đầy đủ - đây là các bit thú vị:
private final byte[] buf = new byte[256];
private final InputStream in;
...
int i;
while ((i = this.in.read(this.buf, 0, this.buf.length)) >= 0) {
...
}
Các dấu vết ngăn xếp trông giống như
"PIT Stream Monitor" daemon prio=6 tid=0x0000000008869800 nid=0x1f70 runnable [0x000000000d7ff000]
java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:220)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
- locked <0x00000007c89d6d90> (a java.io.BufferedInputStream)
at org.pitest.util.StreamMonitor.readFromStream(StreamMonitor.java:38)
at org.pitest.util.StreamMonitor.process(StreamMonitor.java:32)
at org.pitest.util.AbstractMonitor.run(AbstractMonitor.java:19)
Locked ownable synchronizers:
- None
hoặc
"PIT Stream Monitor" daemon prio=6 tid=0x0000000008873000 nid=0x1cb8 runnable [0x000000000e3ff000]
java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:220)
at org.pitest.util.StreamMonitor.readFromStream(StreamMonitor.java:38)
at org.pitest.util.StreamMonitor.process(StreamMonitor.java:32)
at org.pitest.util.AbstractMonitor.run(AbstractMonitor.java:19)
Locked ownable synchronizers:
- None
Với Sysinternals Process Explorer tôi đã có thể nhận các dấu vết gốc của các chủ đề đó. Thông thường, trên 80% các trường hợp, các vết đống trông như thế này:
ntdll.dll!NtReadFile+0xa
KERNELBASE.dll!ReadFile+0x7a
kernel32.dll!ReadFile+0x59
java.dll!handleRead+0x2c
java.dll!VerifyClassCodesForMajorVersion+0x1d1
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
này cũng xảy ra khá thường xuyên:
ntdll.dll!RtlNtStatusToDosErrorNoTeb+0x52
ntdll.dll!RtlNtStatusToDosError+0x23
KERNELBASE.dll!GetCurrentThreadId+0x2c
KERNELBASE.dll!CreatePipe+0x21a
kernel32.dll!ReadFile+0x59
java.dll!handleRead+0x2c
java.dll!VerifyClassCodesForMajorVersion+0x1d1
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
ntdll.dll!RtlNtStatusToDosErrorNoTeb+0x42
ntdll.dll!RtlNtStatusToDosError+0x23
KERNELBASE.dll!GetCurrentThreadId+0x2c
KERNELBASE.dll!CreatePipe+0x21a
kernel32.dll!ReadFile+0x59
java.dll!handleRead+0x2c
java.dll!VerifyClassCodesForMajorVersion+0x1d1
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
Và đôi khi nó thực hiện phần này của mã:
java.dll!VerifyClassCodesForMajorVersion+0xc3
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
java.dll!Java_sun_io_Win32ErrorMode_setErrorMode+0x847c
java.dll!VerifyClassCodesForMajorVersion+0xd7
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
jvm.dll!JNI_GetCreatedJavaVMs+0x1829f
java.dll!VerifyClassCodesForMajorVersion+0x128
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
jvm.dll+0x88c1
jvm.dll!JNI_GetCreatedJavaVMs+0x182a7
java.dll!VerifyClassCodesForMajorVersion+0x128
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
java.dll!VerifyClassCodesForMajorVersion+0x10b
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
jvm.dll!JNI_CreateJavaVM+0x1423
java.dll!VerifyClassCodesForMajorVersion+0x190
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
jvm.dll+0x88bf
jvm.dll!JNI_CreateJavaVM+0x147d
java.dll!VerifyClassCodesForMajorVersion+0x190
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
java.dll!VerifyClassCodesForMajorVersion+0x1aa
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
java.dll!VerifyClassCodesForMajorVersion+0x1c3
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
java.dll!VerifyClassCodesForMajorVersion+0x224
java.dll!Java_java_io_FileInputStream_readBytes+0x1d
Bất kỳ ý tưởng nào về cách giải quyết vấn đề này? Đây có phải là vấn đề đã biết với JVM không? Có cách giải quyết nào không?
Bạn có thể đưa mã vòng lặp của mình không? BTW điều kiện '> = 0' là quá rộng, nếu' buf.length' là khác không, thì read() được đảm bảo để đọc ít nhất 1 byte hoặc trả về -1 (hoặc ném một ngoại lệ). –
Cái gì? 'Process.getInputStream()' có trả về một FileInputStream không? –
Có. Trong java.lang.ProcessImpl # ProcessImpl bạn có thể thấy stdout_stream và stderr_stream được khởi tạo với một FileInputStream. Nó có ý nghĩa từ quan điểm Unix, nơi mọi thứ đều là một tập tin. –