有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从另一个JVM读取一个JVM的输入流

目标:使用ProcessBuilder从单独的JVM(1)初始化JVM(2),捕获JVM(2)的结果输出,并在JVM(1)的JTextArea中显示结果

情况:能够从JVM(1)中启动JVM(2),并将结果从JVM(2)捕获到JVM(1)中的JTextArea

问题:JVM(2)在JVM(1)终止之前不会响应输入

启动JVM(2)的VJM(1)内的线程:

 Runnable runnable = () -> { 

     try {
         JVMBooter.startSecondJVM();
     } catch (Exception ex) {
        Logger.getLogger(MyMenu.class.getName()).log(Level.SEVERE, null, ex);
     }

 };
 Thread t = new Thread(runnable);
 t.start();

JVMBooter源代码:

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;


public class JVMBooter {

    public static void startSecondJVM() throws Exception {

        ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "startscript.bat");
        File dir = new File("D:/Server");
        pb.directory(dir);
        Process p = pb.start();

        BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line = null;

        ( (line = reader.readLine()) != null && ! line.trim().equals("--EOF--")) {

            OutputFrame.textArea.append(line + "\n");
        }

    }

}

JVM(2)在startscript中启动。bat文件包含:

java -jar server.jar

共 (1) 个答案

  1. # 1 楼答案

    根据具体情况,可能需要读取错误流而不是输入流,例如,如果第二个java调用是-version,或者您调用的程序只写入stderr而不是stdout,那么获取错误流是正确的方法

    我写了这篇MCVE:

    import java.io.*;
    
    public class Starter {
        public static void main(String[] args) throws IOException {
            ProcessBuilder pb = new ProcessBuilder("./dosomething.sh");
            File dir = new File(new File(File.listRoots()[0], "tmp"), "2jvm");
            pb.directory(dir);
            Process p = pb.start();
    
            BufferedReader read = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            String line;
            while ( (line = read.readLine() ) != null) {
                System.out.println("line: " + line);
            }
        }
    }
    

    还有一些东西。嘘这个:

    echo before
    java -version
    echo after
    

    当我使用p.getInputStream时,我会得到'before'和'after'。当我使用p.getErrorStream时,我会得到Java版本信息。 对你来说可能也是这样。我建议你在批处理文件中添加echo行,看看它们是否被打印出来

    我还编写了一个简单的hello world,当我从dosomething.sh调用它时,它按预期打印到了输入流中。向stderr写入是一种{a1}of{}

    为了完整起见,这里是我使用的Hello World(它需要等待以模拟长时间运行的服务器进程):

    public class Caller {
      public static void main(String[] args) {
        synchronized(Caller.class) {
          for(int ii = 0; ii < 10; ii++) {
            try {
              Caller.class.wait(1000);
            } catch (Exception ex) {
              ex.printStackTrace();
            }
            System.out.println("Hello world! " + ii);
          }
        }
      }
    }