4

I need to start jar and provide input to it. I've found how to start jar, which works without problems, using Runtime#getRuntime#exec, and I've also found that

String command = "stop";
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
bufferedWriter.write(String.format("%s\n", command));
bufferedWriter.flush();

should do the job. But the problem is, it just doesn't work for me, it literally does nothing. Does anyone know how to do that? Process:

    public static Process startJar(File jarFile, String flags, String args, @Nullable File dir) throws IOException {
        if (dir == null){

            return Runtime.getRuntime().exec(String.format("cmd /c start /wait \"\" java -jar %s \"%s\" %s",flags ,jarFile.getAbsolutePath(), args));

        }
        return Runtime.getRuntime().exec(String.format("cmd /c start /wait \"\" java -jar %s \"%s\" %s", flags, jarFile.getAbsolutePath(), args), null, dir);


    }
kyngs
  • 75
  • 1
  • 6
  • Can we see more code? What's `process`? – byxor Jun 17 '20 at 16:08
  • I think your question/problem is [similar to this one](https://stackoverflow.com/questions/54359170/issue-in-calling-python-code-from-java-without-using-jython). The answer I made relies on the `ProcessBuilder` class, you may want to take a look at. – Patrick Jun 17 '20 at 16:31

3 Answers3

2

If the input is commandline args, pass it to exec directly.

If not, and assuming process is the other jar you are running, you'll need to write to the InputStream of process, not the OutputStream. process.getOutputStream() will give you the stream to which the process is outputting its results, not where it's reading its input from.

EDIT: After Taschi pointed out that the code is correct

I found another question similar to yours. The accepted answer states that you have to either close the writer or pass a \n in order for it to work. Try that. If it still doesn't work, make sure the other JAR you're running is actually waiting for input on its STDIN.

Meet K.
  • 459
  • 3
  • 15
  • That was my first suspicion but according to the API documentation, it is wrong: getOutputStream() is the stream through which you can send output TO the other process, and getInputStream() is the stream through which you get input from it. –  Jun 17 '20 at 16:14
  • Thanks, I will try it. – kyngs Jun 17 '20 at 16:15
  • @Taschi Can you share the exact link of the page where you read this, please? – Meet K. Jun 17 '20 at 16:17
  • Sorry, I don't know how to write into InputStream, and I doubt it is even possible, can you please tell me how? – kyngs Jun 17 '20 at 16:17
  • 1
    @MeetK. https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html –  Jun 17 '20 at 16:18
  • @Taschi Well I'll be damned, you're almost definitely right. Please share the code, kyngs. It will clear things up. – Meet K. Jun 17 '20 at 16:22
  • Indeed the Input/Ouput stream nature of the class Process can be confusing at first. The Process class adopts the point of view of the "master" process. The input of the child process is an output for the master (the master writes to the child); conversely, the std and error outputs of the child process are inputs for the master. – Patrick Jun 17 '20 at 16:23
  • @MeetK. If you look closely, you can see that I'm passing \n in the writer. I tried to close the writer after that, but it still doesn't work. But the jar doesn't have a problem with accepting input, I can normally write commands there. – kyngs Jun 17 '20 at 16:41
  • @kyngs Debug your master process and copy the command being generated by `String.format()` inside the `exec()` call. Use that exact command string to manually run the other jar and check if it responds to manual inputs as intended. – Meet K. Jun 17 '20 at 16:49
  • @MeetK. I'm interacting with the Bukkit server, so I can't put a command on start. – kyngs Jun 17 '20 at 16:50
  • @kyngs Haven't used Bukkit, so no idea how it works. Can you at least verify whether the command being generated by `String.format()` is correct or not? – Meet K. Jun 17 '20 at 16:58
  • @MeetK. I've verified that the generated command is "stop", which should stop the server. – kyngs Jun 17 '20 at 17:46
  • @kyngs This will definitely need some debugging. If it's only a question of starting & stopping the server from another Java program, I can setup the environment on my local machine and use a single class to relay commands and debug. Your thoughts? – Meet K. Jun 17 '20 at 17:58
  • @MeetK. That would be great, but how do you want to do that? – kyngs Jun 17 '20 at 18:02
  • @MeetK. But couldn't theoretically be the problem that I start a new window and in that window, I execute that jar? "cmd /c start /wait \"\" java -jar %s \"%s\" %s" – kyngs Jun 17 '20 at 18:04
1

I assume your process is blocked because it tried to write something to its output, and you did not read it. The API doc states:

Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

So, read from process.getInputStream() and process.getErrorStream() unless both of them are empty, and then it should process your input just fine.

See here: Starting a process in Java? for a possible example on how to read.

  • Should InputStream#reset do the job? – kyngs Jun 17 '20 at 16:19
  • Possibly? But I doubt it. –  Jun 17 '20 at 16:20
  • reading through both streams didn't solve anything. – kyngs Jun 17 '20 at 16:29
  • 1
    Have you tried dumping the other program's output to the console? That might give you some insight as to what is going on. Also, does the program react to input if you run it on the command line, rather than launch it from inside your program? –  Jun 17 '20 at 16:35
  • 1
    Rather than explicitly reading from the input streams, you could redirect them to the std output and error streams of your master program. Of course that means that outputs of the master and child program will be mixed together but it may be good enough to start debugging your programs. – Patrick Jun 17 '20 at 16:37
0

The problem was, that I was starting that jar in a new window (cmd /c start), after removing that, everything works without a problem.

kyngs
  • 75
  • 1
  • 6