Саморазрушающее приложение

Вдоль строк "Эта лента будет самоуничтожаться через пять секунд. Удачи, Джим"...

Возможно ли, чтобы приложение удалило себя (или его исполняемую форму обертки) после достижения установленного времени использования или другого условия?

В качестве альтернативы, какие другие подходы могут быть использованы для того, чтобы приложение было бесполезным?

Цель состоит в том, чтобы истечь срок действия бета-версии, предлагая пользователям получить более актуальную версию.

Ответы

Ответ 1

Это возможно. Чтобы обойти блокировку JAR файла, вашему приложению может потребоваться создать фоновый процесс, ожидающий, пока JVM не выйдет перед удалением файла.

Однако это не является бомбоустойчивым. Кто-то может установить приложение, а затем сделать установленные файлы и каталоги доступными только для чтения, чтобы ваше приложение не могло удалять себя. Пользователь (или их администратор) через систему контроля доступа OS's имеет окончательное мнение о том, какие файлы создаются и удаляются.

Ответ 2

Если вы контролируете, где тестеры загружают ваше приложение, вы можете использовать автоматическую систему сборки (например, Jenkins), чтобы вы могли создать новую бета-версии каждую ночь, которая имеет жестко запрограммированную дату истечения срока действия:

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

указанная дата автоматически вставлена ​​процессом сборки

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

Смешайте это с подписанными и запечатанными банками, чтобы помешать препятствовать декомпиляции байт-кода и обеспечить альтернативную реализацию, которая не включает этот код, вы можете выдать бета-версию кода, истекающего по истечении времени.

Автоматическая система сборки может быть настроена на автоматическую загрузку бета-версии на сервер, на котором установлена ​​версия для скачивания.

Ответ 3

Так как Windows блокирует файл JAR во время его запуска, вы не можете удалить его из собственного кода Java, поэтому вам нужен файл Batch:

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 класс:

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());
    }
}

Решение, вдохновленное этим вопросом.


Вот лучший способ для 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 + "\"");
}

Здесь - оригинальный ответ.

Ответ 4

Это вполне возможно, я думаю. возможно, вы можете удалить банку, как это, и убедитесь, что приложение исчезло, учитывая, что у вас есть права.

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

также использовать что-то вроде Nullsoft Scriptable Install System, которая позволяет вам писать свой собственный установленный/деинсталлятор.