I am trying to write a chatbot. I am still in my startings, but I do have one question.
Process proc = Runtime.getRuntime().exec("notepad.exe");
This actually makes it impossible to quit my program, unless I quit the notepad. Is it possible to quit the Java program before this notepad has ended?
You can run an external program via a separate thread in your program and continue your program logic in your main thread, i.e. a multi-threaded application is a good solution.
First destroy the subprocess :
Process proc = Runtime.getRuntime().exec("notepad.exe");
proc.destroy();
If this doesn't work, get the process id of the process and run a different subprocess to run kill <pid>
then exit java with System.exit(0); or normally.
Related
I have a Java program which starts another process with ProcessBuilder like the following:
String commands[] = {"ruby", "/home/scripts/script.rb"};
ProcessBuilder builder = new ProcessBuilder(commands);
Map<String,String> map = builder.environment();
map.put("TYPE", "sometype");
try {
builder.start();
} catch (IOException e) {
e.printStackTrace();
}
Some time after the process starts executing (a small Ruby Script which should not terminate) the Java program exits.
The problem is, once the Java program finishes executing, all sub-processes are closed, also the Ruby Script.
I found some similar questions but the answer was always, the Process is independent. But it is not like that in my case, the Ruby code will always stop executing if the Java program exits.
I tried the Java code on a Debian Jessie System with Java 8u66
The problem is, once the Java program finishes executing, all sub-processes are closed, also the Ruby Script.
On *nix systems (POSIX really, including Debian Linux) the process is sent a HUP signal (SIGHUP or hangup) when its' parent process ends. You can use the nohup(1) command when you start a subprocess to ignore the hangup from the child process.
Alternatively, you could potentially make use of the Ruby Signal Module and use Signal.trap(HUP) to handle it some other way.
Try to use Process.getOutputStream, wait for output from the process with runs Ruby, and if it takes too much time, then you can run in the background also.
In a Java program I am running another Java program using the following command:
Process p = Runtime.getRuntime().exec("echo.bat | java -Xms64M -Xmx1G -cp "+execFilePath+" "+inputFileName+" "+inputParam);
The invocation is working fine, but if due to bad coding the executed Java file (inputFileName) is hanging, say, due to some infinite loop, a new process which got started, is not ending. Now, I need to kill that process in my code.
I am able to detect if the Java program is hanging by using TimeOut. But, I don't know how to get the process id of this executed Java program and kill it once TimeOut happens.
Any help is appreciated!
Generally, you can call destroy on your Process instance. See here
I notice however that you are starting one process and pipe its output to another. The simple approach will most probabely only kill the former (your echo.bat process).
Therefore, you need a more complex scenario. Do the following:
Start a process calling echo.bat only
Wait until it is finished
Read all of its output through its output stream (Process.getOutputStream())
Start another process, calling the java program only.
Write the read data to its input (write to Process.getInputStream())
This second process instance will be your java process
As fge mentioned above, take a look at ProcessBuilder, as it simplyfies some of the steps. Especially setting up the input stream can be accomplished before actually starting the program
Firstly i have googled this question and the only answers i seem to get are using System.exit(0); which isn't what i am looking for. Currently i am opening a program using
Runtime runtime = Runtime.getRuntime();
runtime.exec("C:\\Program Files\\program folder\\program.exe");
This sucessfully opens the program. However closing the program looks like a completely different kettle of fish. Is it possible to close the program through java due to permissions and security? Also can this be done using runtime or is this more complex issue? As i can see that a windows only solution would be to use
taskkill /IM program.exe
However my question would be, if i initiated a taskkill would this shut down the program straight away? or would it tell the program to start to initiate the shutdown process?
Edit:
I Will advise that the program that will be initiated will deal with an access database
You get a Process back when you do the runtime.exec. On that process instance, there is a destroy method:
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec("C:\\Program Files\\program folder\\program.exe");
p.destroy()
You can do:
Process p2 = runtime.exec("c:\\windows\\system32\\taskkill /IM program.exe")
it is a standard kill not a forceful one (that requires /F), hence it will simply notify the program it should terminate spontaneously.
I could not try with your program, but I opened notepad typed some text and before saving, I used this way to terminate it and notepad asked me if I wanted to save my work.
With the /F option notepad was terminated immediately leaving the file unsaved.
This is the same difference you have in unix between kill vs and kill -9.
Note that this will terminate all the instances of you process, otherwise you should use the pid.
And if your program upon signaling will be able to comply and try to close the open connections and terminate, it will depend on the program itself.
I have a java program that is supposed to run a bat file, and then exit with a success code 0.
The code essentially looks like this
Runtime.exec(....);
System.exit(0);
99.8% of the time, this works perfectly. But very sporadically the bat file won't get run.
My theory is that on certain systems, the Runtime.exec can't finish its spawning before the System.exit runs. Is this likely/possible?
I looked at the source of Runtime.exec but it drops into native code to do the interesting stuff.
EDIT
Based on the answers so far, I should state that the .bat file executes another java process using javaw. I can confirm that the 1st java process ending does NOT kill the 2nd one run in the bat file.
Is it possible that when the problem happens the bat file hadn't spawned the 2nd java process before the System.exit occurred? Perhaps it is not a Runtime.exec problem after all?
EDIT2
I cannot wait for the 2nd process to end, it could run indefinitely and my 1st process must exit.
Try to change to ProcessBuilder. Maybe it works better.
You are creating a child process that will terminate with its parent. You must use Process.waitFor in Java to ensure that Java process waits for the bat process to finish.
System.exit(0) kills jvm instance. All process will be terminated. If you want to really execute System.exit(0), make sure exec process is done before calling System.exit.
Use Process.waitFor(), the return type of this method is int which gives you the return code as per your current solution using Runtime.
waitFor() causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
Change it to
Runtime.getRuntime().exec(....).waitFor();
System.exit(0);
But then this will wait for batch file to complete execution and in your case completion of javaw instance.
I've inherited a Java web-services code-base (BEA/Oracle Weblogic) and need to start/launch an external background application from a web-service.
I've already tried:
ProcessBuilder pb = new ProcessBuilder(arg);
pb.start();
as well as:
Runtime.exec(cmdString);
But am experiencing strange behaviors when launching applications in this manner (i.e. the launched application stops working even though the process is still active. -- The application works fine when manually run from a normal command line).
Is there a better way to launch an external processes?
EDIT: ----------------------
I have some additional information that may help shed some light on the problem.
The process we are trying to start will require hours to complete so waiting for completion (using waitfor()) in the webservice will not be an ideal scenario.
Yes, the process we are trying to start from the webservice was created by a fellow team member [cue: your eyes roll... now]
I have had success when I use process builder to start a bash script, where the external application is launched as a background process (using "&").
#!/bin/bash
java -jar myApp.jar &
This obviously creates an orphaned process but at least the application does continue to execute.
Simply put: if the launched application writes to SDTOUT/STDIN and you don't flush them frequently (see Process.getErrorStream/Process.getInputStream) then the process will block when the buffer is full (that is really small, 4KB or less).
I recommend you to invoke ProcessBuilder.redirectErrorStream() before starting the process. Then, after that, create a thread with the run() method along the lines of:
public void run() {
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
By "stops working even though the process is still active" I am assuming you might be expecting some output from the application you have launched and not getting anything.
Try using the following:
ProcessBuilder pb = new ProcessBuilder(arg);
Process p = pb.start();
p.waitFor();
waitFor() causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
http://java.sun.com/javase/6/docs/api/java/lang/Process.html#waitFor()
Firstly, is this happening on Windows or on Linux? Also, what is the launched application supposed to more or less do? (is it a script? is it a binary? is it your binary?)
EDIT
OK, so starting a bash script (using ProcessBuilder) which in turns spawns a new JVM (java -jar myApp.jar) works.
What happens exactly when you try to spawn the new JVM directly using ProcessBuilder? You originally said:
the launched application stops working
By launched application do you mean "java -jar myApp.jar", when invoked directly, not via an intermediate bash script?
What are the exact and complete parameters (and their values) you pass to the various ProcessBuilder methods (and in which order) when you try to launch Java directly and this new JVM stops working? (e.g. provide annotated code)
If you install lsof on your *nix machine, what file is shown to be associated with file descriptor 2 (look at the FD column) when running: lsof -p 1234 (where 1234 is the process ID of the "hung" JVM?) It might be interesting to attach the entire output of the lsof command here.
What is appended to the file you have identified in step 3 above (for file descriptor 2), up to several seconds after you issue the command: kill -QUIT 1234 (where 1234 is the process ID of the "hung" JVM?)
Are you properly handling the standard input and output of the process? If the standard input or output is being processed by your application and you are not properly handling it, then the process you execute will hang waiting for I/O.
A way to test this is to write a script that runs your program, redirecting standard input, output and error to files. Then have your web service app run the script instead of the program. If the program runs to completion this way, then the problem is handling of the output of the process.
I'm guessing that the problem might be the thread that launches the process gets TERMINATED or whatever after the request is over. Try having a single thread in the applicaton that you are sure is kept alive always, you can use this for starting the processes by making calls to it from other threads.