I need to update my application. To do this, I delete the .jar file my program is currently running from and create a new one with the same name, then restart the application.
However, when I attempt to do this I get a java.io.IOException: Access is denied.
How can I fix this?
Thanks!
The problem is, the jar files are been used by the JVM (specifically, the class loaders). Even under Java 7, where the jar files are closed by the class loaders when the are no longer needed, there is no guarantee that the underlying resources will be released, or more specifically, when they will be released.
For some more information, take a look at Closing a URLClassLoader
You have a few choices.
You Could...
Separate your update process from your application (so it's a standalone program) and use parentless execution process to update the application. This involves executing your program in such away that it allows the current process to terminate before the new process, under windows this can be achieved using something like...
cmd /c start /b /normal "" {command line to be executed}
Under Linux I believe you can use nohup, but I have no experience with that.
(Don't forget to use System.exit to terminate the current process ;))
You Could...
You could use Java Web Start which provides it's own updating capabilities
Related
I want to run a (java) application in a docker container. This application has an update functionality. This is run automatically on startup and can be triggered manually from the (web) GUI. The update downloads the new files, then runs the new executable (with new PID) and exits itself.
Usually, I use the exec java -jar MyProgram.jar "$#" in entrypoint.sh. This will stop the container when an update occurs (because PID=1 exits).
Just using the line without exec does not correctly forward SIGTERM/SIGKILL for docker stop. While forwarding these signals is possible as explaned here in program.sh, I don't know how to track PIDs when an update occurred and a new process is spawned.
Update: Since I am not the developer of the application, I am looking for a solution without modifying the applications.
Update 2: I found out that the application creates a MyProgram.pid file which I can read to kill it with the help of a trap as explained in program.sh linked above.
Typically we bake jars into an image. If we update the jars in a container at runtime, when we stop the container we lose those changes. Normal upgrade practice is to update your app spec with the new jars and rebuild it into an image using a pipeline of some sort, then replace your containers with the new ones.
I have a java program that should run on a Windows machine. It should run "forever", i.e. when the JVM or the program crashes, it should be restarted. When the computer is restarted it should also be restarted.
I saw advice to wrap the program as a "Windows service", but the tools I found seem to be either costly, complicated or outdated.
Can somebody describe me a straightforward way to achieve the desired behaviour?
For the part where you want to start the program after restart you can create a simple batch (.Bat) file and u can put that file in the startup folder.
Also you can use the same file for running the program when it crashes. you can use tasklist command and check if your java program is running and if it is not .just start the program.
Just check our windows batch this is one of the best things you can get everything for doing anything on windows without anything expensive
Yet Another Java Service Wrapper is a tool that easily wraps your Java program into a Windows service. Just start the program, note down the PID and enter it into the wrapper. Two things, which are probably universal to services, should be noted:
For connection to the network, you need to specify an account with the necessary rights.
Connected network drives are not available.
This question is not as simple as telling me to use runas; Please read the question before answering.
When I use C on UNIX/Linux and want to write a program to run with elevated privilege, I use this flow:
program starts.
process lowers privilege using setuid().
process does unprivileged work.
process raises privilege using
setuid().
process does privileged work such as opening a
restricted file.
process lowers privilege using setuid().
The critical part of the flow is that the process lowers its privilege immediately after starting and only raises its privilege long enough to do the corresponding work.
How can I do a similar thing on Windows using Java?
My specific use case is that I want to read and write protected files such that the only way for the user of the program to access the files is thru my Java program. I do not want to run the entire process with Administrator privilege just to protect a couple of files.
The JRE by itself does not allow this. There are two options to do it in "Java":
Use JNI to make C calls into the OS
Script out the calls that use setuid() (use a script language or create a C executable) and have the JVM exec that script.
I believe the more difficult part of your problem will be finding a setuid() equivalent in Windows. See https://serverfault.com/questions/16886/is-there-an-equivalent-of-su-for-windows. The most straightforward way would be to wrap runas (yes, I said it) in a script or perhaps exec your script with runas. See Run command prompt as Administrator for ideas on how to do that.
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.
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.