2012-04-16 29 views
22

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?

+3

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ệ). –

+0

Cái gì? 'Process.getInputStream()' có trả về một FileInputStream không? –

+0

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. –

Trả lời

1

Tôi đã chưa thể tái tạo này tại địa phương, nhưng hai cách giải quyết tốt có thể là

  • Chơi xung quanh với in.available().

  • Redirect mập mạpstderr trong quá trình bên ngoài để một ổ cắm và đọc từ quá trình kiểm soát thay thế.

+0

[Sửa nhanh bằng cách sử dụng in.available()] (http://code.google.com/p/pitestrunner/source/browse/pitest/src/main/java/org/pitest/util/StreamMonitor.java?spec = svn0607ac947dd76768f5e852350386bc9c324a6005 & r = 0607ac947dd76768f5e852350386bc9c324a6005 # 59) đã giúp tránh sự cố hiện tại. Chúng tôi vẫn đang tìm kiếm một giải pháp tốt hơn và lý do tại sao điều này xảy ra ngay từ đầu. Tôi sẽ cố gắng tạo ra một [SSCCE] (http://sscce.org/) bằng cách loại bỏ mã thừa ra khỏi dự án nguồn đóng mà tôi có thể tái tạo nó. –

+0

Vấn đề có thể được tái sản xuất bằng cách đâm vào tiến trình con với mảng phân bổ vô hạn vòng lặp từ http://stackoverflow.com/questions/65200/how-do-you-crash-a-jvm và có lẽ các kỹ thuật khác được liệt kê ở đó . – henry

Các vấn đề liên quan