Java: Get a process given a pid - java

Say I have a current running process known, how can I turn this into a Process object in Java?
The process is already running, so I don't want to spawn off another one, I just want to encapsulate it into a Process object that I can use within the java code.
Something along the lines of:
int pid = getPid();
Process proc = magicGetProcess(pid);
thanks

I don't think this is possible using only the builtin library. AFAIK, it is already non-trivial to get the running process' own PID (see the feature request and alternate mechanisms).
A quick look at the java.lang.Process class shows that you could go about writing your custom implementation of java.lang.Process using JNI and native code. Your custom class could then implement extra methods, such as the one in your question.

In *nix world grabbing exit code of a non-child process is not easy, because the exit code simply disappears together with the process as soon as the parent process has picked up the exit code of the child. You can attach to the running process using some tracing tool and pick up its exit code when the process dies. Most *nix OSes have command line tools which will let you do it (such as strace on Linux, truss on SunOS) in a non-intrusive way. However, you can only use them against your own processes or if you run as root. Another alternative is to configure audit subsystem of your OS to record exit codes of all processes.

You can't. Every operation in Process requires that the process is a child process. Not an arbitrary process.

what about using RMI? It it possible to pass a Process object to the Process which it is? Probably not, because Process is not Serializable

Related

Exit java program to linux command

I'm making a little tool that handles a sort of exotic device, with lots of options to manage it etc. One of them would be to scan for tty ports, find the right one then throw the user to "minicom" with some parameters for example.
How can I make java completely exit while running a specific command, under certain condition, after such exit ?
Initial thoughts would be to use a bash script, scan the return value, communicate via files etc.A fully functional interactive serial console in Java would be the dream, but the ones I try right now can't seem to even find tty ports now.
Most processes on linux follow a call stack where process A calls process B which calls process C.
Wen process C terminates, the control goes back to process B, and so on.
It sounds like in this case you want java to call minimum, but when java is finished, return to the parent shell.
I am not aware of any way you can terminate a JVM upon a call to another process (returning to the JVM's parent when it terminates). Perhaps with some clever C calls using JNI, but that isn't really java anymore and could create new problems.
You could have the JVM wrap the target process and pass through the user inputs and outputs. Alternatively, use file communication, e.g. the java program writes the command-line to a file, that the parent bash script executes after the JVM terminates, but that is a bit of a kludge.

Gwt process id which run using runtime.getExec("<tcl file>") function

I need to execute a tcl file which gives output util we stop the process from java. So I use
Process proc = Runtime.getRuntime().exec("< tcl file >");
I need to get the process id (PID) to stop the process.I can run that same tcl file multiple times, so I can't get pid using getting name of executing file. Give me some methods to get process id using JAVA when running a external program.
output of ps command :
25014 pts/0 00:00:00 tclfile
29998 pts/0 00:00:09 tclfile
30866 pts/0 00:00:00 tclfile
Each instance is different I need to stop only specified process at a time, can't terminate all by killall -9 tclfile command .
The pid is not exposed to Java, since Java is platform-agnostic and pids are platform-specific. So you aren't going to be able to get the actual pid without using native code, sorry.
But if you just want a handle to the child process which you can later kill, you can do that in pure Java. The Process object has methods destroy() (which kills the process) and waitFor() (which waits for it to exit). In Java 8 it also has isAlive() and destroyForcibly() methods.
OK, after poking around on the net to find source code for ProcessImpl in various JREs, it looks like on Windows ProcessImpl has a field handle which presumably is the Win32 handle returned by CreateProcess, and on Linux UNIXProcess has a field pid which appears to be the process ID. If you wanted to be really hacky (and unsupported, and potentially tied to a specific JDK implementation, etc. -- all the usual caveats apply), you could potentially access those fields by reflection if you need to.
That said, a better solution would be to write the native code yourself, or else delegate to a helper process (e.g. in bash like Donal Fellows' answer).
You can't get the process ID from the Process object; it knows it (strictly, it's known by an object inside of a class that isn't part of the public API) but won't tell you. The simplest method of getting the PID turns out to be to get the subprocess to tell you that value by writing it to its standard out (or standard error, but that's less common) as its first action. You then can just read a line, parse the integer out of it, and there you go.
Getting Tcl scripts to print their PID is trivial. Just put this line in:
puts [pid]
# Or: puts stdout [pid]
If you can't change the Tcl script, you can use a shell script trick to wrap it in something that writes the value:
#!/bin/sh
echo $$
# exec, in bash, *replaces* the process implementation with another program
exec tclsh "$#"

How to suspend/resume a process created by ProcessBuilder in Java

ProcessBuilder.start() returns a Process object through which I can access the 3 streams (STDIN, STDERR, STDOUT) of the new process.
Unfortunately, I couldn't find a way to access the process id of the created process through the Process interface. Is there a way to access the process id?
Beyond this, I wished to do something like calling SuspendProcess() and ResumeProcess() [Win32 APIs]
Is there a way to do these things in Java?
There isn't one. If you are in control of the started process you could have it read its stdin for stop/start messages, and write them from the starting Java code via Process.getOutputStream().
Maybe this could help you.
How can a Java program get its own process ID?

Spawn a process in Java that survives a JVM shutdown

I need to spawn a process in Java (under Linux exclusively) that will continue to run after the JVM has exited. How can I do this?
Basically the Java app should spawn an updater which stops the Java app, updates files and then starts it again.
I'm interested in a hack & slash method to just get it working as well as a better design proposal if you have one :)
If you're spawning the process using java.lang.Process it should "just work" - I don't believe the spawned process will die when the JVM exits. You might find that the Ant libraries make it easier for you to control the spawning though.
It does actually "just work", unless you're trying to be clever.
My wrapped java.lang.Process was trying to capture the script's output, so when the JVM died, the script didn't have anywhere to send output so it just dies. If I don't try to capture the output, or the script doesn't generate any or redirects everything to a file or /dev/null, everything works as it should.
I was having trouble with this and the launched process was getting killed when the JVM shutdown.
Redirecting stdout and stderr to a file fixed the issue. I guess the process was tied to the launched java app as by default it was expecting to pass its output to it.
Here's the code that worked for me (minus exception handling):
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectOutput(logFile);
pb.redirectError(logFile);
Process p = pb.start();
I thought the whole point of Java was that it's fully contained within the JVM. It's kinda hard to run bytecode when there's no runtime.
If you're looking to have a totally separate process you might look into trying to start a second java.exe instance. Although for your application, it might be easier to simply make a synchronized block that stops (but doesn't kill) your app, does the updating, and then re-initializes your app's data.
It won't always "just work". When JVM spawns the child and then shuts down, the child process will also shutdown in some cases. That is expected behaviour of the process. Under WIN32 systems, it just works.
E.g. If WebLogic server was started up by a Java process, and then that process exits, it also sends the shutdown signal to the WebLogic via shutdown hook in JVM, which causes WebLogic to also shutdown.
If it "just works" for you then there is no problem, however if you find yourself in a position that child process also shutsdown with JVM it is worth having a look at the "nohup" command. The process won't respond to SIGTERM signal, but will respond to SIGKILL signal, as well as normal operations.
Update: The way described above is a bit of an overkill. Another way of doing this would be to use "&" on the end of command. This will spawn a new process that is not a child of current java process.
P.S. Sorry for so many updates, I have been learning and trying it from scratch.
>>don't believe the spawned process will die when the JVM exits.
Child process is always dying on my box(SuSE) whenever I kill java. I think, the child process will die if it's dealing with I/O of the parent process(i.e., java)
If you're looking at making an updater on Linux, you're probably barking up the wrong tree. I believe all major linux distros have a package manager built in. You should use the package manager to do your updating. Nothing frustrates me more than programs that try to self-update... (I'm looking at you, Eclipse)

Is it possible to kill a Java Virtual Machine from another Virtual Machine?

I have a Java application that launches another java application. The launcher has a watchdog timer and receives periodic notifications from the second VM. However, if no notifications are received then the second virtual machine should be killed and the launcher will perform some additional clean-up activities.
The question is, is there any way to do this using only java? so far I have to use some native methods to perform this operation and it is somehow ugly.
Thanks!
I may be missing something but can't you call the destroy() method on the Process object returned by Runtime.exec()?
You can use java.lang.Process to do what you want. Once you have created the nested process and have a reference to the Process instance, you can get references to its standard out and err streams. You can periodically monitor those, and call .destroy() if you want to close the process. The whole thing might look something like this:
Process nestedProcess = new ProcessBuilder("java mysubprocess").start();
InputStream nestedStdOut = nestedProcess.getInputStream(); //kinda backwards, I know
InputStream nestedStdErr = nestedProcess.getErrorStream();
while (true) {
/*
TODO: read from the std out or std err (or get notifications some other way)
Then put the real "kill-me" logic here instead of if (false)
*/
if (false) {
nestedProcess.destroy();
//perform post-destruction cleanup here
return;
}
Thread.currentThread().sleep(1000L); //wait for a bit
}
Hope this helps,
Sean
You could also publish a service (via burlap, hessian, etc) on the second JVM that calls System.exit() and consume it from the watchdog JVM. If you only want to shut the second JVM down when it stops sending those periodic notifications, it might not be in a state to respond to the service call.
Calling shell commands with java.lang.Runtime.exec() is probably your best bet.
The usual way to do this is to call Process.destroy()... however it is an incomplete solution since when using the sun JVM on *nix destroy maps onto a SIGTERM which is not guaranteed to terminate the process (for that you need SIGKILL as well). The net result is that you can't do real process management using Java.
There are some open bugs about this issue see:
link text
OK the twist of the gist is as follows:
I was using the Process API to close the second virtual machine, but it wouldn't work.
The reason is that my second application is an Eclipse RCP Application, and I launched it using the eclipse.exe launcher included.
However, that means that the Process API destroy() method will target the eclipse.exe process. Killing this process leaves the Java Process unscathed. So, one of my colleagues here wrote a small application that will kill the right application.
So one of the solutions to use the Process API (and remove redundant middle steps) is to get away with the Eclipse launcher, having my first virtual machine duplicate all its functionality.
I guess I will have to get to work.
java.lang.Process has a waitFor() method to wait for a process to die, and a destroy() method to kill the subprocess.
You can have the java code detect the platform at runtime and fire off the platform's kill process command. This is really an refinement on your current solution.
There's also Process.destroy(), if you're using the ProcessBuilder API
Not exactly process management, but you could start an rmi server in the java virtual machine you are launching, and bind a remote instance with a method that does whatever cleanup required and calls System.exit(). The first vm could then call that remote method to shutdown the second vm.
You should be able to do that java.lang.Runtime.exec and shell commands.

Categories

Resources