Self-destructing application

僤鯓⒐⒋嵵緔 提交于 2019-11-28 00:45:06
Stephen C

It is possible. To get around the lock on the JAR file, your application may need to spawn a background process that waits until the JVM has exited before deleting stuff.

However, this isn't bomb-proof. Someone could install the application and then make the installed files and directories read-only so that your application can't delete itself. The user (or their administrator) via the OS'es access control system has the final say on what files are created and deleted.

If you control where testers download your application, you could use an automated build system (e.g. Jenkins) that you could create a new beta versions every night that has a hard-coded expiry date:

private static final Date EXPIRY_DATE = <90 days in the future from build date>;

the above date is automatically inserted by the build process

if (EXPIRY_DATE.before(new Date()) {
    System.out.println("Get a new beta version, please");
    System.exit(1);
}

Mix that with signed and sealed jars, to put obstacles in the way of decompiling the bytecode and providing an alternative implementation that doesn't include that code, you can hand out a time-expiring beta of the code.

The automated build system could be configured to automatically upload the beta version to the server hosting the download version.

Since Windows locks the JAR file while it is running, you cannot delete it from your own Java code hence you need a Batch file:

private static void selfDestructWindowsJARFile() throws Exception
{
    String resourceName = "self-destruct.bat";
    File scriptFile = File.createTempFile(FilenameUtils.getBaseName(resourceName), "." + FilenameUtils.getExtension(resourceName));

    try (FileWriter fileWriter = new FileWriter(scriptFile);
         PrintWriter printWriter = new PrintWriter(fileWriter))
    {
        printWriter.println("taskkill /F /IM \"java.exe\"");
        printWriter.println("DEL /F \"" + ProgramDirectoryUtilities.getCurrentJARFilePath() + "\"");
        printWriter.println("start /b \"\" cmd /c del \"%~f0\"&exit /b");
    }

    Desktop.getDesktop().open(scriptFile);
}

public static void selfDestructJARFile() throws Exception
{
    if (SystemUtils.IS_OS_WINDOWS)
    {
        selfDestructWindowsJARFile();
    } else
    {
        // Unix does not lock the JAR file so we can just delete it
        File directoryFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath();
        Files.delete(directoryFilePath.toPath());
    }

    System.exit(0);
}

ProgramDirectoryUtilities class:

public class ProgramDirectoryUtilities
{
    private static String getJarName()
    {
        return new File(ProgramDirectoryUtilities.class.getProtectionDomain()
                .getCodeSource()
                .getLocation()
                .getPath())
                .getName();
    }

    public static boolean isRunningFromJAR()
    {
        String jarName = getJarName();
        return jarName.contains(".jar");
    }

    public static String getProgramDirectory()
    {
        if (isRunningFromJAR())
        {
            return getCurrentJARDirectory();
        } else
        {
            return getCurrentProjectDirectory();
        }
    }

    private static String getCurrentProjectDirectory()
    {
        return new File("").getAbsolutePath();
    }

    public static String getCurrentJARDirectory()
    {
        try
        {
            return getCurrentJARFilePath().getParent();
        } catch (URISyntaxException exception)
        {
            exception.printStackTrace();
        }

        throw new IllegalStateException("Unexpected null JAR path");
    }

    public static File getCurrentJARFilePath() throws URISyntaxException
    {
        return new File(ProgramDirectoryUtilities.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
    }
}

Solution inspired by this question.


Here is a better method for Windows:

private static void selfDestructWindowsJARFile() throws Exception
{
    String currentJARFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath().toString();
    Runtime runtime = Runtime.getRuntime();
    runtime.exec("cmd /c ping localhost -n 2 > nul && del \"" + currentJARFilePath + "\"");
}

Here is the original answer.

Anurag Ramdasan

it is pretty possible i guess. maybe you can delete the jar like this and make sure the application vanishes given that you have the rights.

File jar = new File(".\\app.jar");
jar.deleteOnExit();
System.exit(0);

also using something like Nullsoft Scriptable Install System which enables you to write your own installed/uninstaller should help.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!