2011-09-19 27 views
6

Tôi đang sử dụng ProcessBuilder của Java để bắt đầu một tiến trình con, là một chương trình Java khác phải chạy trong một JVM riêng biệt.Subprocess bắt đầu từ kết thúc Java bằng cách sử dụng waitFor nhưng các luồng không bị chấm dứt

Tôi bắt đầu hai Chủ đề để đọc từ luồng stdout và stderr từ Quy trình, để không bị treo nếu bộ đệm luồng đầy. Cuộc gọi đến Process.waitFor trả về nhưng các luồng không bị chấm dứt.

Mã Tôi đang sử dụng ngoại hình giống như (lệnh là một danh sách các chuỗi):

ProcessBuilder pb = new ProcessBuilder(command); 

final Process p = pb.start(); 
final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 
final ByteArrayOutputStream errStream = new ByteArrayOutputStream(); 

Thread outputThread = new Thread() { 
    @Override 
    public void run() { 
     try { 
      IOUtils.copy(p.getInputStream(), outStream); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }; 
}; 
outputThread.start(); 

Thread errorThread = new Thread() { 
    @Override 
    public void run() { 
     try { 
      IOUtils.copy(p.getErrorStream(), errStream); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }; 
}; 
errorThread.start(); 

int returncode = p.waitFor(); 
outputThread.join(); 
errorThread.join(); 

Nếu tôi chạy cái gì khác, chẳng hạn như "java -version" hoặc "dir" hoặc một cái gì đó, mã hoạt động tốt. Tôi có quyền truy cập vào mã Java mà tôi đang cố gắng chạy, nhưng tôi chưa bao giờ nghe nói rằng bạn nên gọi close() trên System.out.

+0

Bạn có thể quan tâm đến câu hỏi của tôi về đóng Process' suối thích hợp: http://stackoverflow.com/questions/7065067/how-to-close-std -streams-from-java-lang-process-thích hợp Một liên kết hữu ích khác: http://mark.koli.ch/2011/01/leaky-pipes-remember-to-close-your-streams-when-using- javas-runtimegetruntimeexec.html –

+0

Nếu tôi sử dụng 'IOUtils.closeQuietly' hoặc thậm chí gọi' close() 'trên các luồng trước các cuộc gọi' join() ', chương trình sẽ treo trên cuộc gọi đó. –

+0

Điều này có lẽ là do 'IOUtils.copy (in, out)' sử dụng 'InputStream.read (byte [])' và đó là chặn và chờ dữ liệu đến. Do đó các luồng đang chạy mãi mãi và do đó 'join()' chờ đợi mãi mãi. Bạn đã buộc phải đóng ở đây sau khi hết thời gian chờ nhất định. Hãy thử thực hiện như một trong tôi đăng trong câu trả lời của tôi từ liên kết tôi đã cho bạn. Tôi sẽ đặt cược nó có thể xử lý này ở đây. –

Trả lời

0

Như tôi biết từ this website, bạn phải đóng tất cả các luồng từ đối tượng Quy trình theo cách của riêng bạn. Bất kể nếu được sử dụng trước đó hay không. Điều này dường như có liên quan cao đến bộ thu gom rác G1 (mặc định kể từ Java 7 afaik), giúp cho các đường ống được mở ra khi không đóng một cách rõ ràng - ngay cả khi quá trình con đã kết thúc.

Tôi không quen thuộc với nội bộ ở đây nhưng mã tôi đăng trong my answer cho câu hỏi của tôi hoạt động tốt trên một hệ thống 24/7 gọi GhostScript và những người khác rất nhiều.

câu hỏi khác và câu trả lời về SO nói rằng bạn phải đóng Process' std-suối rõ ràng:

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