Cross-platform way to change java process priority - java

I need to invoke .jar file in separate JVM from another java application, and it very CPU-consuming, so it should run with background priority in order not to affect the rest of the system. Is there any cross-platform method to do this?

The simple answer is that there is no portable way to change the priority of a Process in Java. (Threads - yes, Processes - no.)
If your Java application needs to start a new JVM to run the CPU intensive application, then the chances are that it is already not entirely portable. For example, you will typically need to give the pathname of the java command (or equivalent), a -cp argument (or equivalent), system specific JVM options, and so on.
So, assuming that the command to launch the JVM is already non-portable, it should hardly matter if you replace the command with a wrapper script that does OS-specific things to change the priority of the launched process. (For example, for UNIX or Linux you could simply use nice to launch the JVM.)

I don't know the way to set the priority for an external process. Thread however has a setPriority method, so if you control the target application, you could perhaps add a switch, telling the application to set its own priority to minimum:
theThread.setPriority(Thread.MIN_PRIORITY);
If it still affects the system, I suggest you interleave some short sleeping to offload the cpu.
Another option:
If you put the target .jar in the classpath of the "initiating" application, you can simply invoke the main-method of the jar-file in a newly created thread, and then set the priority using the above method. (This should work even if you don't control the source-code of the target jar file.)

Related

Kill / Stop an application with Java Code

Is it possible to stop an application in windows using java code ?
I'd like to create a program which is like a shortcut to stop an application on my pc. Is it possible using ProcessBuilder ? Thank you
Plain Java, without native access? No.
ProcessBuilder lets you control processes that you started from within the Java application, but it doesn't give you control to processes that were started by other processes.
As per user988052's comment, you can use pskill from the Sysinternals Suite to accomplish this through Runtime.exec. pskill uses the TerminateProcess function call. You can also call this function with JNI (or some other native caller, like JNA, NLink, etc.), but you'll need to obtain a handle to the process via the OpenProcess function call.
Is it possible to stop an application in windows using java code ? ... Is it possible using ProcessBuilder ?
Only if you launched the application from the same Java application that you are trying to fill it from.
Other than that, you need to resort to running a Windows-specific command to do the killing ... or something based on JNI to make native Windows library calls.
The other complications are that you may not be able to kill certain processes due to permissions issues, and some process may refuse to be killed.
I believe the JRE does not provide an API for system processes. ProcessBuilder can create system processes, but it cannot provide you with a Process object for a process created outside the JVM. I believe that is a philosophical decision on the part of the Java folks, to avoid certain OS-specific tasks where possible. You might think that every OS has pids, or that they all have some kind of kill message, but Java runs on lots of OSes, some of them quite strange.
You could make native code to do it and wrap that with JNI, but that would be wasteful. As Mr 988052 says, I suggest you execute a system-specific command through Runtime.exec or ProcessBuilder. You would need to decide which OSes you want to support, and be sure to get the commands (and the OS-detection code) right for each one.

Some questions about Java Threads and Process Priorities

I have a small question about threads.
On Unix systems, we have nice, which can be used to set priorities
processes.
OK, on ​​my system, I call some external processes, however, I would like to
set priority for them.
In unix, I could call other ProcessBuilder and set the nice to
process I want, but in Windows, it is not possible.
If I start a thread with some priority, and use within ProcessBuilder
it, the process will have the same priority as thread?
Or is there some other way to do this?
Cheers
There's no way to set priority on a process (Process) level in Java.
If I start a thread with some priority, and use ProcessBuilder within it, the process will have the same priority as thread? Or is there some other way to do this?
The process will run side by side with the JVM, so it will not inherit the threads priority. It will be scheduled on it's own by the operating system.
As stated above, there is no built in cross-platform way of tweaking the priority of a process, but there is a Thread.setPriority(int) though. So perhaps you could do the work by the external program in a separate thread (instead of starting a new process) and use the setPriority method on this thread.
Related questions / answers:
Cross-platform way to change java process priority
How to change the priority of a running java process?
You could write a C/C++ DLL and export a JNI function that calls SetPriorityClass
You could then use this in your java code

How to pause process run using Java's ProcessBuilder.start()?

Alright, so I'm writing this program that essentially batch runs other java programs for me (multiple times, varying parameters, parallel executions, etc).
So far the running part works great. Using ProcessBuilder's .start() method (equivalent to the Runtime.exec() I believe), it creates a separate java process and off it goes.
Problem is I would like to be able to pause/stop these processes once they've been started. With simple threads this is generally easy to do, however the external process doesn't seem to have any inbuilt functionality for waiting/sleeping, at least not from an external point of view.
My question(s) is this: Is there a way to pause a java.lang.Process object? If not, does anyone know of any related exec libraries that do contain this ability? Barring all of that, is extending Process a more viable alternative?
My question(s) is this: Is there a way to pause a java.lang.Process object?
As you've probably discovered, there's no support for this in the standard API. Process for instance provides no suspend() / resume() methods.
If not, does anyone know of any related exec libraries that do contain this ability?
On POSIX compliant operating systems such as GNU/Linux or Mac OS you could use another system call (using Runtime.exec, ProcessBuilder or some natively implemented library) to issue a kill command.
Using the kill command you can send signals such as SIGSTOP (to suspend a process) and SIGCONT (to resume it).
(You will need to get hold of the process id of the external program. There are plenty of questions and answers around that answers this.)
You will need to create a system for sending messages between processes. You might do this by:
Sending signals, depending on OS. (As aioobe notes.)
Having one process occasionally check for presence/absence of a file that another process can create/delete. (If the file is being read/written, you will need to use file locking.)
Have your "main" process listen on a port, and when it launches the children it tells them (via a comamnd-line argument) how to "phone home" as they start up. Both programs alternate between doing work and checking for handling messages.
From what you have described (all Java programs in a complex batch environment) I would suggest #3, TCP/IP communication.
While it certainly involves extra work, it also gives you the flexibility to send commands or information of whatever kind you want between different processes.
A Process represents a separate process running on the machine. Java definitely does not allow you to pause them through java.lang.Process. You can forcibly stop them using Process.destroy(). For pausing, you will need the co-operation of the spawned process.
What sorts of processes are these? Did you write them?

Reconstruction of java command line arguments

Is there a way to reconstruct the command line arguments passed to Java within a Java program, including the JVM options and classpath option?
I have a Java program that needs to restart the JVM and manipulate its bootclasspath (i.e. trying to override some system classes). I use the libc system method to invoke the new JVM.
I'm open for better approaches, but Java agents isn't an option.
Why not use a file that has these properties just like the Eclipse ini file and NetBeans conf files. That way you just read these properties and spawn the new Java process with these properties.
Back to your question, this previous answer should do
I agree that futzing with the bootclasspath is generally a poor idea. But...
Grab the code for "java.c" - the C program that compiles down to java.exe. You'll find that it just uses the JNI Invocation API to construct a JVM and call the main method. You could modify and re-compile this to look for particular exit codes, etc. and loop around and re-launch the JVM if required.
Alternatively, Eclipse does this (or at least used to), but having one Java program construct the command line (from a props file, etc.) and launch a sub-process. Again, it hooked the sub-process exit code and used that to decide whether or not to re-launch a new sub-process.
Err... modifying a whole core java class at runtime is a very very bad idea.
Whats wrong with subclassing here? Are you trying to modify an external library, add functionality, or be lazy?

Is there a way to include a VM parameter inside a .jar?

I have a game implemented in Java that was having a problem when running too much code from scripts: depending on the script language, the game could have these "hiccups" where the game would freeze for a couple frames every now and then, making the game "jerky" at times.
After some research, I discovered that was happening when the Garbage Collector decided to run. After some more research and testing, I discovered that using the incremental garbage collector (by using the -Xincgc VM parameter) fixed the problem. Yes, I am aware it makes the GC run about 10% slower, but it is the cost I pay.
With that background information, now what I want to do is package the game in a .jar like I have been doing so far, but I know no way of making the application use the incremental GC without using -Xincgc, and I didn't want to create .bat/.sh files where before the user only had to double-click the .jar.
Is there any way to make the .jar run with the incremental GC without needing some kind of loader (.bat/.sh) or wrapper around it? Is there some way to include that parameter in the .jar?
No, there's no way to do that. VM arguments can only be supplied as command-line parameters to JVM invocation: Java Tool
You can definitely do this with JNLP, which can be configured to add a shortcut to the desktop and automatically keep jars up to date, among other things.
From just a jar file, you can't do this. Adding Java WebStart can allow you to add java VM commands. If you are not against wrapping the jar in an executable Launch4J will wrap the jar in a executable as well. It only makes a windows exe, but it can make it on linux or windows. I haven't found a good alternative for linux.
I don't know of too many java apps outside of internal coorporate or dev stuff that people run via clicking a jar. Even a shortcut can specify this. Fancier options exist that let you create an exe, run as a service, or even wrap the whole thing in an installer... if we are talking windows, similar things exist for linux.
Besides Java Web Start, you could consider wrapping with JSMooth. It gives an EXE which in turn invokes the JVM - you can provide arguments there.
One option - I always wondered - is to re-run the jar program with Runtime.exec() call when the parameters are inadequate? Never tried it but seems possible.

Categories