簡體   English   中英

Java ProcessBuilder限制

[英]Java ProcessBuilder Limits

我有一個通過套接字連接到本地服務器的Java程序,如果Java檢測到它沒有運行,我不想手動啟動服務器。 因此,如果Java未連接到服務器,那么我將使用ProcessBuilder來啟動它:

new ProcessBuilder(new String[]{"/bin/bash", "-c", "./start_server"}).start();

這將啟動服務器,並運行約4分鍾,直到服務器進程無響應。 有趣的是,如果我發送更多命令,則花費的時間更少。 我想知道我是否遇到ProcessBuilder的限制,可能使用了過多的內存。 我將通信打印到服務器端的服務器上,因為這是從ProcessBuilder調用的,所以我認為它是指向其他地方的,這就是問題所在。

您必須讀取stdout和stderr的輸出(即使只是將其丟棄)。 否則,輸出緩沖區將填滿,從而導致異常行為。

最簡單的方法是重定向到位存儲桶(假設Java 1.7+):

File bitbucket;

if (isWindows()) {
    bitbucket = new File("NUL");
} else {
    bitbucket = new File("/dev/null");
}

Process process = new ProcessBuilder("/bin/bash", "-c", "./start_server")
                  .redirectOutput(ProcessBuilder.Redirect.appendTo(bitbucket))
                  .redirectError(ProcessBuilder.Redirect.appendTo(bitbucket))
                  .start();

但是,如果必須使用Java 1.6或更低版本,則必須自己滾動。 這是我在項目中使用的:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamConsumer
{
    private final InputStream stream;

    private StreamConsumer(InputStream is)
    {
        this.stream = is;
    }

    private Runnable worker()
    {
        return new Worker();
    }

    private class Worker implements Runnable
    {
        @Override
        public void run()
        {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
                while (br.readLine() != null) {
                    /* No one cares */
                }
            } catch (IOException ioe) {
                /* No one cares */
            }
        }
    }

    public static void consume(InputStream stream, String label)
    {
        Thread t = new Thread(new StreamConsumer(stream).worker(), label);
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();
    }
}

您可以這樣稱呼它:

Process process = new ProcessBuilder("/bin/bash", "-c", "./start_server")
                      .start();

StreamConsumer.consume(process.getInputStream(), "STDOUT");
StreamConsumer.consume(process.getErrorStream(), "STDERR");

或像這樣:

Process process = new ProcessBuilder("/bin/bash", "-c", "./start_server")
                      .redirectErrorStream(true)
                      .start();

StreamConsumer.consume(process.getInputStream(), "STDOUT/STDERR");

請注意, ProcessBuilder構造函數使用String... (變量),而不是String[] (盡管您可以根據需要手動創建和傳遞String[]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM