2

I need a JAR file to delete itself.

The issue is that Windows locks the JAR file while it is running, and can't delete itself directly.

I have looked into solutions where a batch script could kill the JAR process and then delete the file, but

  • System.exit(0) is not desired because it is not runnable via Batch file.
  • taskkill /F /IM "java.exe" is not desired because it kills ALL Java processes.
  • jps cannot be used because it is only available in the JDK and users might run a JRE so that would fail.

I'm stuck on looking for a solution which lets me find the PID of the current JAR using Java code, then writing out a Batch command and inserting the PID which kills the process e.g. like the following:

printWriter.println("taskkill /PID " + currentJARPID);

If you're wondering what this is for, you can check this answer.

phflack
  • 2,729
  • 1
  • 9
  • 21
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • Can the java file read the bat file output, waiting for a kill command? Or must you kill the file from the bat file, without interacting with the java file? – phflack Oct 30 '17 at 15:01
  • @phflack: I have to kill the `Java` process from the batch file so that the `JAR` is no longer locked and can be deleted. Deleting cannot be done from within the `Java` code since it cannot run and delete itself at the same time due to file locking on `Windows`. – BullyWiiPlaza Oct 30 '17 at 15:07
  • I understand that, I will rephrase the question: can the java process read the .bat output – phflack Oct 30 '17 at 15:09
  • Also related [How can a Java program get its own process ID?](https://stackoverflow.com/q/35842/5475891) – phflack Oct 30 '17 at 15:19
  • Does the process you are considering actually work reliably at all? Presumably it will work if the JVM shuts down -- the lock on the executable is released -- more quickly than the batch file can be loaded and executed. I concede that things might work this way, but I don't see how it can be guaranteed. Could you not launch the JVM from a batch file, and then have that batch file delete the JAR once the JVM has exited? – Kevin Boone Oct 30 '17 at 15:46
  • @KevinBoone: The JAR is started normally via double-click and at any time the code may decide to self-destruct the JAR. The current strategy works because when the process is killed, the lock is already released before the JAR is attempted to be deleted. If this order is not ensured, one may just loop in the batch file and check if the file still exists, then try to delete and repeat till it succeeded. Finally, the batch file can delete itself to clean up since there is no lock on the batch file when it executes. – BullyWiiPlaza Oct 30 '17 at 21:01
  • "the code may decide to self-destruct the JAR" - can this code be in the JAR itself, or must it be in the bat script? – phflack Oct 31 '17 at 12:28
  • @phflack: In the bat script because Java cannot delete its own `JAR` executable while it's running. I just need the `taskkill` by `PID` of the running `JAR` part via batch. – BullyWiiPlaza Oct 31 '17 at 21:11
  • I highly suspect this is an [XY problem](https://meta.stackexchange.com/q/66377), what is your overall goal? If you're just trying to delete the jar file, it's very different from requiring the bat file to kill the jar process – phflack Nov 01 '17 at 12:05
  • @phflack: No. I just want the `JAR` to be able to delete itself and it can't be done while it's running due to file locking so calling a batch script to do it is the best idea since the `JAR` locking only happens on `Windows`. Therefore, there is no way to do this in `Java` code. – BullyWiiPlaza Nov 01 '17 at 13:39
  • You just denied that this is an XY problem, then explained how this is an XY problem – phflack Nov 01 '17 at 14:39
  • @phflack: I don't care what it is, can you please just help solve the question like you should when commenting? I'm just looking for some proper implementation of this functionality. You provided no suggestions or alternatives whatsoever besides some pointless XY problem claims. My actual problem is **deleting a JAR file by itself** and the attempted solution is **using a batch file** because there is no better way. I already made this very clear I thought. – BullyWiiPlaza Nov 01 '17 at 14:51
  • You did not make your intentions clear. This is what an XY problem is, you ask for something difficult when there are easier solutions. You asked for a batch command that will kill a specific process, and how to get the process ID from within java. What you want is for your JAR to delete itself. These are two different problems, and prevented me from answering the real question you have – phflack Nov 01 '17 at 15:10

1 Answers1

6

Here is a working example

public class Delete
{
    public static void main(String[] args) throws Throwable
    {
        System.out.println("Running");

        System.out.println("Deleting");
        Runtime.getRuntime().exec("cmd /c ping localhost -n 6 > nul && del Delete.jar");

        System.out.println("Ending");
        System.exit(0);
    }
}

The main feature powering this is cmd /c ping localhost -n 6 > nul && del Delete.jar

It deletes the jar file after waiting 5 seconds

To test, I used javac Delete.java && jar cfe Delete.jar Delete Delete.class to build the jar, and java -jar Delete.jar to run

I also verified that I could not delete the jar file while it was executing, through new File("Delete.jar").delete(); and also using Windows Explorer

phflack
  • 2,729
  • 1
  • 9
  • 21