I am working in an java application where i want to make sure that a given process in the computer is idle
ex:- if we start a download process in our computer my application should be able to monitor it (process) and tell when it is over,
Most operating systems provide user commands to monitor activity of a process, like CPU or I/O. Or, at a higher level, you can get the status (running or not) of a process by its process identifier. You could exec these tools from Java, but there's nothing in core Java to do this, nor am I aware of any libraries for this purpose.
However, if you are thinking about killing a process because it is "idle", that generally wouldn't be safe. You have to know enough about the process in question to be sure it's okay to kill it, and if you know that much about it, you'll probably find that there's a way to get it to shut itself down cleanly.
If you start the process from another process, you can detect when it finishes with Process.waitFor() You can even use its exit code.
Related
So I am trying to have a Java program that starts running when the main method is invoked and stops running when the same main method is invoked (from another process). So the goal is to kill the first process with the second process, and then kill itself.
What I have tried are the following:
taskkill for Windows and kill for Unix.
This is the simplest way to do achieve the goal. But the process in Windows is always javaw.exe and calling taskkill would terminate other JVMs.
ServerSocket or DatagramSocket, to tell the first process to kill itself.
This works as well but I feel like this is just a waste for such a simple job.
File locks
The problem is that the permission of creating a file is not always granted (for whatever reason someone decides to use the program in read-only folders).
I think I might just missed something obvious. Any suggestions would be appreciated.
Hi all i Have two process in my java application as below.
Process p1=some process;
Process p2=some process;
At the first time it starts its working perfectly.But when i reload the application the older process is also running so i just want to kill the older process if its executing.I know that we can kill a process by using its process id.But how can i get the process id of this p1 and p2.Any idea?.
Catch the reload event in your application and terminate the child process before you exit.
If that doesn't work, you probably have a bug in your design. Try to fix that bug. Really. I mean it.
A workaround is to write the PID into a text file. When you start, read the text file, check if this is the correct process and then kill it.
Without the check, you might be killing a perfectly valid process which was created by someone else. My reasoning is like so: You can't kill the process when you reload. That means you can't delete the text file either. So the PID file will always exist. Eventually, you will kill the wrong process. That will happen once per year. It will happen the first time six months after you left/changed job/etc. Nobody will understand what is going on because it's almost impossible to reproduce.
As others have said, it would be better to terminate the process in a more natural way.
However, if you do need to actually forcibly terminate it, then you could call the destroy() method on the Process object, whenever you don't care about it running anymore.
Also, do you really need to run the code as a Process? There are generally better ways.
My main purpose is to execute processes one by one in a round-robin fashion until one calls receive() and is blocked, so that the execution switches to the next process in the queue. There is a controller application which is coded in Java and it executes these processes(which are also Java applications) using Runtime.getRuntime().exec() and keeps the return values which are Process objects.
To achieve this purpose, I need to capture the receive() calls(or their states, which is blocked) and tell them to the controller(master) application.
I can go as low-level as you want if this is possible.. My first thought was to get this information from the driver and then tell it to my controller Java application. I have written a linux kernel network module which captures the send and receive operations, but AFAIK the socket.receive() function does not tell anything to the network driver.
So, I think the options are to get this information from either the JVM, somehow get it from a linux command or so, or possibly through the linux kernel module?
What are your suggestions?
If you want to know if your threads are blocked, or exactly what they are blocked on, you can either take a thread dump or use a tool like jvisualvm to attach to the process and take a look (in jvisualvm you would attach to the process, take a thread dump, and then look at the activity of each thread).
Have you looked at systemtap? Should be readily available on recent Fedora systems.
Best
Anders
I don't know if this will help you, but you could get information about the state of a Java thread on your machine using local attach.
1) Add the tools.jar to your classpath and use VirtualMachine.list() to get a list of the running JVM on you machine.
2) Attach to the JVM processed using VirtualMachine.attach(virtualMachineDescriptor)
3) Get the local connector address, vm.getAgentProperties().get("com.sun.management.jmxremote.localConnectorAddress");
4) Use JMXConnectorFactory.newJMXConnector(...) to connect to the JVM
5) From the JMX connection lookup up the ThreadMXBean
6) From the ThreadMXBean you get an array of ThreadInfos that describes all threads in the JVM.
7) From TheadInfo#getThreadState() you can check if the state is ThreadState.BLOCKED
You should use interprocess communication primitives in your worker processes to notify the controller application that they are ready to receive data.
You can't make assumptions about how the child processes implement their socket read. They could be using recv, or select, or poll, etc., to wait for network data.
There are actually a few points here. The Linux scheduler is smart enough to pre-empt a blocked task. Meaning, if you call receive() and there's nothing waiting to receive, your task will probably be put to sleep until such a time that the call will return. You don't need to handle the scheduling; the Linux kernel will do it for you.
That said, if you need to know whether your task is blocked from some daemon application, if you're willing to write an LKM, why not just get the task in the task list that you're interested in, and check its state?
Of course, simply checking the state of the task might not tell you exactly what you want. If your task state is TASK_INTERRUPTIBLE, it only tells you that your task is waiting on something, but it might not be a trivial matter to figure out what that something is. Similarly, your task can be in a TASK_RUNNING state and not actually be running on the CPU at the current moment (but, at least, in the TASK_RUNNING state you know your task isn't blocked).
You can just send a QUIT signal (Ctrl-\ on the console) to get a thread dump.
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)
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.