Is it possible to end a process nicely in a Java application? - java

In a Java application:
currentProcess = Runtime.getRuntime().exec("MyWindowsApp.exe");
...
currentProcess.destroy();
Calling destroy simply kills the process and doesn't allow any user cleanup or exit code to run. Is it possible to send a process a WM_CLOSE message or similar?

You could use Process.getOutputStream to send a message to the stdin of your app, eg:
PrintStream ps = new PrintStream(currentProcess.getOutputStream());
ps.println("please_shutdown");
ps.close();
Of course this means you have to contrive to listen on stdin in the Windows app.

you can try with JNA, importing user32.dll and defining an interface that defines at least CloseWindow

Using JNA's jna.jar and process.jar (from http://jna.java.net/) you send a WM_CLOSE message as follows:
int WM_CLOSE = 0x10;
HWND hwnd = User32.INSTANCE.FindWindow(null, windowTitle);
User32.INSTANCE.PostMessage(hwnd, WM_CLOSE, new WinDef.WPARAM(), new WinDef.LPARAM());

Not without resorting to native code. Process.destroy() causes a forced termination. On Windows this is equivalent to calling TerminateProcess(). On Unix it is equivalent to a SIGQUIT and causes the application to core dump.

A dirty solution would be making your MyWindowsApp register its identifier somewhere like file and create another windows app that sends WM_CLOSE (let's name it MyWindowsAppCloser) to another applications.
With this in hand, you would code the following using java 1.6
currentProcess = Runtime.getRuntime().exec("MyWindowsApp.exe");
...
// get idMyWindowsApp where MyWindowsApp stored its identifier
killerProcess = new ProcessBuilder("MyWindowsAppCloser.exe", idMyWindowsApp).start();
killerProcess.waitFor();
int status = currentProcess.waitFor();

Related

C# - Stop ServiceProcess wrapper after java process is stopped

I'm building a c sharp serviceProcess that will start a Batch file (the batch file will start a java application).
If i stop the service it kills the java process. Stopping the java process can take up to 2 minutes. The service has to wait for the java application to stop, so i made a sleep.
System.Threading.Thread.Sleep( );
Is it possible to check if the "java" process is closed and after that stop the ServiceProcess.
You can access the process using the Process-class. It allows you to get several information about a specific process. When you start the java.exe directly (using Process.Start) you already have the Process-instance.
When using a batch-file, you need to find the process, which is not a problem at all. You can find a process using Process.GetProcessesByName, but you'd find all all java-processes running on your machine.
You could try something like the following:
Process[] proc = Process.GetProcessesByName("Java");
if (proc.Count() != 0)
{
//Process Alive
Process prod = proc[0];
prod.Kill();
prod.WaitForExit();
}
else
{
//Process Dead
}
A better option would be to use the process ID(if you know it)
Warning: This will kill the first java process it finds, you need to check which one you need to kill...

How to run Different commands from Java Code?

I want to run different commands which can be executed on my command prompt or terminal through Java.
I did search few place but did not get appropriate reply.
I want to run a compiler which is set in the environment as VISAGE_HOME as well as run GRADLE so as to do all my build tasks.
I want to invoke all these commands from within Java Program.
Since it is a swing application I would like to invoke these commands on click of button or some other events.
My Problem is that I am not able to program this :( .
Neither do I know an API which would do this. I went through some sample codes but most of them have same kind of example codes of executing the shell commands or command prompt commands. None showed me to do the above stuff.
Have a look at ProcessBuilder. The Process object it returns has a waitFor method so you can wait for the process to finish. Then you can start your next process.
For example
Process p = new ProcessBuilder("runYourCommand").start();
InputStream in = process.getInputStream();
InputStreamReader inr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(inr);
String inputLine;
while ((inputLine = br.readLine()) != null) {
System.out.println(inputLine);
}
p.waitFor();
Another interesting method on ProcessBuilder is environment(). This will return the environment variables that you can access. From the API docs
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
Something like this:
String cmd = "gedit";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
Firstly, ProcessBuilder is your friend...
You could have a look at;
Getting started with Java’s ProcessBuilder (Linux focus)
Using ProcessBuilder to Make System Calls
Run processbuilder and get in and output
ProcessBuilder and how redirecting input and output from operating system's processes
Executing Operating System Commands from Java
Secondly, You will need to use System.getenv to find the value of the specified environment variable and substitute it yourself.
nb: Thanks to Guillaume Polet for pointing out that the Process will automatically include the path environment variable to find commands.
Also, remember, DO NOT EXECUTE ANY BLOCKING PROCESS ON THE EDT.
Executing external commands are inherently blocking actions, while not explicitly, taking into account needing to consume the output of the process or wanting to know about the processes termination, these would require you to perform some kind of blocking action. Don't do this on the EDT. It will cause you program to appear as if it's hung.
You can use the Runtime.exec methods to run commands from within Java. The system enviroment variables are normally not visible from within the jvm. You could use a launcher, that submits these system enviroment properties as jvm properties to your java application.
According to http://javarevisited.blogspot.de/2011/02/how-to-execute-native-shell-commands.html implementing the following into your code after including "java.lang.Runtime" should perfectly work:
try {
Process process = Runtime.getRuntime().exec("Command to be executed");
} catch (Exception e) {
e.printStackTrace(System.err);
}

How to stop the execution of Java program from Command line?

My main field is .Net but recently I have got something to do with Java. I have to create a shell utility in Java that could run in background reading few database records after specified duration and do further processing. It's a kind of scheduler. Now I have few concerns:
How to make this work as a service. I want to execute it through a shell script and the utility should start running. Off course the control should get back to the calling script.
Secondly, eventually i may want to stop this process from running. How to achieve this?
I understand these are basic question but I really have no idea where to begin and what options are best for me.
Any help / advise please?
I would go for the running the program using a scheduler or a service. However, if you wish to use a bat file and do this programmatically, I have outlined a possible approach below:
In your Java program, you can get the PID programmatically, and then write it to a file:
public static void writePID(String fileLocation) throws IOException
{
// Use the engine management bean in java to find out the pid
// and to write to a file
if (fileLocation.length() == 0)
{
fileLocation = DEFAULT_PID_FILE;
}
String pid = ManagementFactory.getRuntimeMXBean().getName();
if (pid.indexOf("#") != -1)
{
pid = pid.substring(0, pid.indexOf("#"));
}
BufferedWriter writer = new BufferedWriter(new FileWriter(fileLocation));
writer.write(pid);
writer.newLine();
writer.flush();
writer.close();
}
You can then write a stop .bat file that will kill the running program in windows. You could do something like:
setlocal
IF EXIST app.pid FOR /F %%i in ('type app.pid') do TASKKILL /F /PID %%i
IF EXIST app.pid DEL app.pid
endlocal
Of course, app.pid is the file written by the Java method above.
I am not sure how you would be able to write a script that launches a java program, and reverts control on termination. I would be interested to see if anybody has a solution for that.
I assume that you are playing your java program with a Linux/Unix box.
To run your application as a daemon, you can try
nohup java YourJavaClass &
To stop your application, you can either:
kill [psIdofYourApplication]
or
fg [your application job Id]
Ctrl-C
If you want to do some postprocessing after the application receiving 'kill/stop' signal. check out addShutdownHook(Thread hook)
Or sun.misc.SignalHandler
ps ux
see pid
kill pid
Or you'd better provide a stopping script that signals the application, which does System.exit(0)
You didn't specify the platform. If on Windows you should look into integrating with the Service Control to create a Windows service. http://en.wikipedia.org/wiki/Windows_service. Once you've implemented the service hooks, it is possible to start and stop the service through the service control GUI or using net stop MyService syntax from the command line.
As I understand, you want something like this:
if ( System.in.avaliable() > 0 ) {
in = new BufferedReader( new InputStreamReader( System.in );
String InLine = in.readLine();
...
}
Am I right?

What is the purpose of Process class in Java?

Runtime objRuntime = Runtime.getRuntime();
String strBackupString = "mysqldump -u " + userName + " -p" + password + " " + dbName;
Process objProcess = objRuntime.exec(strBackupString);
This is used for backup of database. But what exactly happens? Can anybody make me explain, what is the purpose of Runtime and Process class?
Is this class used to act as if we are typing command from command prompt? Then what should i pass to objRuntime.exec() if i want to open notepad? And is the command executed as soon as we call exec method? If yes, then what purpose does Process serve here? I really can't understand these two classes. Please make me understand. Thanks in advance :)
Whenever in doubt, always consult the API:
java.lang.Process
The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process that can be used to control the process and obtain information about it. The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.
Runtime.exec(String command)
Executes the specified system command in a separate process.
So yes, Runtime.exec can execute a command that you'd usually type in the system command prompt. This is hardly a platform-independent solution, but sometimes it's needed. The returned Process object lets you control it, kill it, and importantly sometimes, redirect its standard input/output/error streams.
Related questions
Is java Runtime.exec platform independent?
How to create a process in Java
Get output from a process
Runtime.getRuntime().exec()
API links
java.lang.Process
java.lang.ProcessBuilder
java.lang.Runtime
notepad.exe example
As mentioned before, this is platform dependent, but this snippet works on my Windows machine; it launches notepad.exe, and attempts to open test.txt from the current working directory. The program then waits for the process to terminate, and prints its exit code.
public class ExecExample {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec("notepad.exe test.txt");
System.out.println("Waiting for notepad to exit...");
System.out.println("Exited with code " + p.waitFor());
}
}
It's an object-based representation of a process. Similar to the Thread class, which represents a thread.

How can I replace the current Java process, like a unix-style exec?

I have a server written in Java that runs as a Windows service (thanks to Install4J). I want this service to be able to download the latest version of the JAR file it runs from, and start running the new code. The stitch is that I don't want the Windows service to fully exit.
Ideally, I would accomplish this by a unix-style exec() call to stop the current version and run the new one. How can I best accomplish this?
Here is a complicated, but portable, way.
Split your code into two jars. One very small jar is there just to manage process startup. It creates a ClassLoader that holds the other jar on its classpath.
When you want to load a new version, you terminate all threads running code from the old jar. Null out all references to instances of classes from the old jar. Null out all references to the ClassLoader that loaded the old jar. At this point, if you didn't miss anything, the old classes and ClassLoader should be eligible for garbage collection.
Now you start over with a new ClassLoader instance pointing at the new jar, and restart your application code.
As far as I know, there is no way to do this in Java.
I suppose you could work around it by using the Java Runtime.exec or ProcessBuilder's start() command (which start new processes) then letting the current one end... the docs state
The subprocess is not killed when
there are no more references to the
Process object, but rather the
subprocess continues executing
asynchronously.
I'm assuming the same is true if the parent finishes and is garbage collected.
The catch is Runtime.exec's process will no longer have valid in, out, and err streams.
Java Service Wrapper does this and more.
You could use the built in reloading functionality of for example Tomcat, Jetty or JBoss, they can be run as a service, and you don't have to use them as a web container or Java EE container.
Other options are OSGi, and your own class loading functionality.
But be aware of reloading in a production environment. It is not always the best solution.
General approach:
import java.io.BufferedInputStream;
import java.util.Arrays;
public class ProcessSpawner {
public static void main(String[] args) {
//You can change env variables and working directory, and
//have better control over arguments.
//See [ProcessBuilder javadocs][1]
ProcessBuilder builder = new ProcessBuilder("ls", "-l");
try {
Process p = builder.start();
//here we just echo stdout from the process to java's stdout.
//of course, this might not be what you're after.
BufferedInputStream stream =
new BufferedInputStream(p.getInputStream());
byte[] b = new byte[80];
while(stream.available() > 0) {
stream.read(b);
String s = new String(b);
System.out.print(s);
Arrays.fill(b, (byte)0);
}
//exit with the exit code of the spawned process.
System.exit(p.waitFor());
} catch(Exception e) {
System.err.println("Exception: "+e.getMessage());
System.exit(1);
}
}
}

Categories

Resources