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.
Related
Im creating a javafx application to run a unix binary application, which limits the percent of cpu a process can use, herein i already have a cputhrottle unix binary which receives PID and CPU percentage as argument, my application just acts as a GUI for this unix binary.
When I run this cputhrottle from terminal it keeps on running, until i press - CTRL+C (this is the normal behavior).
But the problem is, when I run this unix binary with my java code, it seems, as if the program is almost immediately terminated (whereas it should be running, until I press the stop button), and because its not running & being terminated, My program cannot control the percentage of CPU a process gets.
Here's my code : http://pastebin.com/rbG3ctfH
so, is there a way to tell java to keep running the cputhrottle binary file, instead of closing it.
I've tried replacing the 56th line, and instead wrote code to execute a script, which would create a file, with some text content, & when executed he program, it did created a file, so its working, but when i add e1.printStackTrace in the catch block, it stops working for some reason.
And also, if I add sleep in the shell script, then its not executed Properly, more over no Exception is being Generated.
The command you are trying to run ("echo dkkdk|sudo....) is a shell command. You need to tell runtime.exec() to run 'bash -c echo dkkdk|sudo..'
Also be aware that runtime.exec is asynchronous and could/might/likely will return to your program before the child process completes.
Also, I could not pipe the superuser password to sudo like you are trying to do. Not saying it doesn't work for you just that I couldn't get my system to take it.
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
There is a couple anomalies I have found here.
Program info:
The program is a parser. It takes in data through a data input stream. Then when the data input stream is closed I call system.exit(0).
dis.close();
System.exit(0);
I have created a jar and exe. When I use the jar it seems to run fine. and everything is as expected. The console looks like this
/the/path/that/im/currently/in
$ <I type:> java -jar myprogram.jar commandLineArg *enter
Program output
Program output
Program output
<program ends and goes back to>
/the/path/that/im/currently/in
$
When I use the exe. The console looks like this, and you can see how it kind of bounces.
/the/path/that/im/currently/in
$ <I type:> ./myprogram commandLineArg *enter
/the/path/that/im/currently/in
$ Program output
Program output
Program output
<now stuck hanging until I hit enter or ctrl+c> *enter
/the/path/that/im/currently/in
$ <now i'm back where I should be>
This sounds like a problem with the tool you used to make the .exe file, it may no longer use a Java Virtual Machine to execute your code, or use one which is inappropriately implemented in that the System.exit(0) call is not recognised as a command to also exit the wrapper process, and as stated by the Javadocs for System.exit(int status):
public static void exit(int status)
Terminates the currently running Java Virtual Machine. The argument
serves as a status code; by convention, a nonzero status code
indicates abnormal termination.
This method calls the exit method in class Runtime. This method never
returns normally.
The call System.exit(n) is effectively equivalent to the call:
Runtime.getRuntime().exit(n)
As such, it may be worth trying another wrapper tool.
System.exit() is a drastic call -- it forces exit of all running threads, rather than allowing them to run to completion. It can be appropriate in cases where you need to communicate an exit code to the OS, or when there are threads you know should be killed. But it is not generally necessary, there are better ways to termnate your program.
We can't tell about yours, of course, unless we know more about the program. But I suspect a hack/quick fix would be to put a Thread.sleep(3000) right before the call to exit().
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.
Can a Java.exe JVM restart itself somehow? If you have a Java program running in a DOS shell (NOT as a service), what is the cleanest, most efficient way for it to shut down, close the shell, and restart itself with a different Windows process id and re-open in a different shell with a reloaded classpath?
I expect it's not possible but I thought I should ask and learn from other people by asking.
NOTE: If anyone knows how Eclipse IDE is able to restart itself so cleanly, that is the method I am wanting to use.
The Java Service Wrapper can help here. You can run your Java process under it but not necessarily as a service. You can define restart characteristics, such that if it exits, the Java program is restarted (either by System.exit() or calling WrapperManager.restart()).
The cleanest and simplest way to do that would be to run the program from a DOS batch file (or CMD script, if you prefer). Build a loop into your DOS batch file. You put a :label near the beginning and a GOTO label below your Java process and off it goes. If need be, you can break out of the loop using Ctrl-C.
Create a separate executable that takes a process ID and a command as command line argument, waits for the specified process to close and then runs the specified command. Launch that program, then exit the current instance.
You can either embed that program in your primary program and copy it to a temporary directory to execute it, or include it side-by-side with your program.