2012-04-16 4 views
22

पर असीमित 100% CPU उपयोग मैं अभी एक प्रोग्राम को डीबग कर रहा हूं जिसमें एक बाहरी प्रक्रिया के दो धागे हैं, और वे दो धागे Process.getErrorStream() को पढ़ते रहते हैं और Process.getInputStream() while ((i = in.read(buf, 0, buf.length)) >= 0) लूप का उपयोग कर।java.io.FileInputStream.readBytes (मूल विधि)

कभी-कभी जब बाहरी प्रक्रिया किसी JVM क्रैश के कारण क्रैश हो जाती है (these hs_err_pid.log files देखें), उस थ्रेड जो बाहरी प्रक्रिया के stdout/stderr को पढ़ते हैं, 100% CPU का उपभोग शुरू करते हैं और कभी बाहर नहीं निकलते हैं। लूप बॉडी को निष्पादित नहीं किया जा रहा है (मैंने वहां एक लॉगिंग कथन जोड़ा है), इसलिए अनंत लूप देशी विधि java.io.FileInputStream.readBytes के अंदर प्रतीत होता है।

मैंने इसे विंडोज 7 64-बिट (jdk1.6.0_30 64-बिट, jdk1.7.0_03 64-बिट), और लिनक्स 2.6.18 (jdk1.6.0_21 32-बिट) दोनों पर पुन: उत्पन्न किया है। प्रश्न में कोड here है और इसका उपयोग like this किया जाता है। पूर्ण कोड के लिए उन लिंक्स देखें - यहाँ दिलचस्प बिट्स हैं:

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) { 
    ... 
} 

स्टैक ट्रेस

"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 

या

"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 
Sysinternals प्रोसेस एक्सप्लोरर मैं करने में सक्षम था के साथ

की तरह लग रहे उन धागे के देशी ढेर निशान प्राप्त करें। अक्सर, समय की 80% से अधिक, स्टैक ट्रेस इस तरह दिखता है:

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 

यह भी अक्सर होता है:

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 

और कभी कभी यह कोड के इस हिस्से को क्रियान्वित कर रहा है:

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 

कोई समस्या इस समस्या को हल करने के लिए कैसे करें? क्या यह JVM के साथ एक ज्ञात समस्या है? क्या आसपास कोई काम है?

+3

क्या आप अपना लूप कोड शामिल कर सकते हैं? बीटीडब्ल्यू स्थिति '> = 0' अत्यधिक व्यापक है, यदि 'buf.length' गैर-शून्य है, तो पढ़ें() कम से कम 1 बाइट या वापसी -1 (या अपवाद फेंकने) को पढ़ने की गारंटी है। –

+0

क्या? क्या Process.getInputStream() 'एक FileInputStream लौटा रहा है? –

+0

हां। Java.lang.ProcessImpl # ProcessImpl में आप stdout_stream और stderr_stream को FileInputStream के साथ प्रारंभ किया जा सकता है। यह यूनिक्स बिंदु दृश्य से समझ में आता है, जहां सब कुछ एक फ़ाइल है। –

उत्तर

1

मैं अभी तक इस स्थानीय रूप से पुन: पेश करने में सक्षम नहीं किया गया है, लेकिन दो संभावित समाधानों हो सकता है

  • in.available() साथ खेलते हैं चारों ओर।

  • पुनर्निर्देशन मोटा और बाह्य प्रक्रिया में stderr एक सॉकेट और को नियंत्रित करने की प्रक्रिया के बजाय से पढ़ें।

+0

[in.available()] का उपयोग कर एक त्वरित फिक्स (http://code.google.com/p/pitestrunner/source/browse/pitest/src/main/java/org/pitest/util/StreamMonitor.java?spec = svn0607ac947dd76768f5e852350386bc9c324a6005 और आर = 0607ac947dd76768f5e852350386bc9c324a6005 # 59) ने अब समस्या से बचने में मदद की है। हम अभी भी एक बेहतर समाधान की तलाश में हैं और यही कारण है कि यह पहली जगह क्यों हो रहा है। मैं बंद स्रोत प्रोजेक्ट से अनावश्यक कोड को हटाकर एक [एसएससीसीई] (http://sscce.org/) तैयार करने का प्रयास करूंगा जहां मैं इसे पुन: पेश कर सकता हूं। –

+0

समस्या को http://stackoverflow.com/questions/65200/how-do-you-crash-a-jvm से लूप आवंटित अनंत सरणी के साथ बाल प्रक्रिया को क्रैश करके फिर से उत्पादित किया जा सकता है और शायद वहां सूचीबद्ध अन्य तकनीकें । – henry

संबंधित मुद्दे