出口清洁问题

Issue cleaning at exit



我正在使用 JSmooth JAVA。
我看到每次启动时都会创建一个 tmp JAR。

创建的 tmp jar 文件大约为 10 Mb。

当我退出由 JSmooth 构建的可执行 JAVA 应用程序时,
每次启动时都会保留临时 jar 文件。

我阅读了以下关于 JSmooth 的主题:
JSmooth - exit application

7.1.2.
What happens to the extracted jar file when the java application exits?

Whenever possible, the wrappers delete the file on exit. Note however that this is not always possible. For example, an instance of a JVM created using the JVM DLL does not unload cleanly. This behaviour (not to call it a bug) is documented by Sun, and there is no known work-around for it.

Both Windowed and Console wrapper always prefer the JVM instanciation methods that allow them to delete the temp jar after the application exits. Note that embedding a jar in the exe is not required, it is always a safe choice to just leave it on the filesystem near the executable, either in the same directory, or in a sibling or parent directory.

Note also that deleting the files in the windows TEMP directory is not required for Windows applications, and most application just leave them, letting the operating system manage it. The standard behaviour of MS Windows is to propose the user to delete the temporary files when the disks are running low on available space.


我试图删除出口处的罐子:

//For matching convention, I wrote the file in a not null package
package main;

import java.io.File;

//It is an utility class, so the class is final
public final class Constants {

    //The tmp folder key
    private static final String TMP_FOLDER = "java.io.tmpdir";

    //The main class
    private static Class<?> _mainClass_ = Constants.class;

    //It is an utility class, so hide the constructor
    private Constants(){
    }

    public static void main(String[] _args) {
        //Processing
        //....
        exit();
    }

    /**@see System#exit(int)*/
    public static void exit() {
        String path_ =_mainClass_.getProtectionDomain().getCodeSource().getLocation().getPath();
        //For keeping portability OS, replace all back slashes by slashes
        path_ = new File(path_).getAbsolutePath().replace("\", "/");

        //For keeping portability OS, replace all back slashes by slashes
        String folder_ = System.getProperty(TMP_FOLDER).replace("\", "/");

        if (path_.startsWith(folder_)) {
            //If the jar is located in the temp folder, then delete it before exit.
            System.out.println("path: "+path_);
            System.out.println("folder: "+folder_);

            //Try remove temp jar
            new File(path_).delete();
            new File(path_).deleteOnExit();
        }
        //Exit the program
        System.exit(0);
    }
}

我的 JSmooth 文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<jsmoothproject>
    <JVMSearchPath>exepath</JVMSearchPath>
    <JVMSearchPath>registry</JVMSearchPath>
    <JVMSearchPath>javahome</JVMSearchPath>
    <JVMSearchPath>jrepath</JVMSearchPath>
    <JVMSearchPath>jdkpath</JVMSearchPath>
    <JVMSearchPath>jview</JVMSearchPath>
    <arguments></arguments>
    <bundledJVMPath>jre</bundledJVMPath>
    <currentDirectory>${EXECUTABLEPATH}</currentDirectory>
    <embeddedJar>false</embeddedJar>
    <executableName>Test.exe</executableName>
    <initialMemoryHeap>-1</initialMemoryHeap>
    <jarLocation>target\Test.jar</jarLocation>
    <mainClassName>main.Constants</mainClassName>
    <maximumMemoryHeap>1073741824</maximumMemoryHeap>
    <maximumVersion>1.7</maximumVersion>
    <minimumVersion>1.7</minimumVersion>
    <skeletonName>Windowed Wrapper</skeletonName>
    <skeletonProperties>
        <key>Message</key>
        <value>Java has not been found on your computer. Do you want to download it?</value>
    </skeletonProperties>
    <skeletonProperties>
        <key>URL</key>
        <value>http://www.java.com</value>
    </skeletonProperties>
    <skeletonProperties>
        <key>SingleProcess</key>
        <value>0</value>
    </skeletonProperties>
    <skeletonProperties>
        <key>SingleInstance</key>
        <value>0</value>
    </skeletonProperties>
    <skeletonProperties>
        <key>JniSmooth</key>
        <value>0</value>
    </skeletonProperties>
    <skeletonProperties>
        <key>Debug</key>
        <value>1</value>
    </skeletonProperties>
</jsmoothproject>

我认为计算机可用 space(每次启动时,免费 space 减少 10 Mb)非常危险 因为电脑可能出问题了。

我希望,我的问题是准确的,我没有白白打扰别人。
非常感谢能够抽出时间回答的人。

Java 无法删除当前正在 Windows 下使用的文件。这是 Windows.

的限制

这意味着任何通过 file.delete()file.deleteOnExit() 从您的程序中删除它们的尝试都将失败。这也是导致JSmooth出现bug,无法删除文件的原因。

虽然你不能直接删除文件,但是你可以启动一个像cmd这样的辅助程序来安排10秒左右后删除文件,这可以通过运行退出时的以下内容来完成你的程序:

new ProcessBuilder("cmd","/c","ping 127.0.0.1 && del "+filename).inheritIO().start();

因为Windows 没有合适的命令行休眠命令,我滥用ping 命令在运行 下一个命令之前延迟3 秒。这个技巧的解释是:How to sleep for 5 seconds in Windows's Command Prompt? (or DOS)

@Ferrybig:
最后,

我删除了所有以前的 tmp jar 文件,
因为临时文件中的程序写入tmp jar文件是非常罕见的。

此外,如果使用tmp jar文件,删除它会失败,所以在执行结束时删除是安全的。

我的新代码:

//For matching convention, I wrote the file in a not null package
package main;

import java.io.File;

//It is an utility class, so the class is final
public final class Constants {

    //The tmp folder key
    private static final String TMP_FOLDER = "java.io.tmpdir";

    //The main class
    private static Class<?> _mainClass_ = Constants.class;

    //It is an utility class, so hide the constructor
    private Constants(){
    }

    public static void main(String[] _args) {
        //Processing
        //....
        exit();
    }

    /**@see System#exit(int)*/
    public static void exit() {
        String path_ =_mainClass_.getProtectionDomain().getCodeSource().getLocation().getPath();
        //For keeping portability OS, replace all back slashes by slashes
        path_ = new File(path_).getAbsolutePath().replace("\", "/");

        //For keeping portability OS, replace all back slashes by slashes
        String folder_ = System.getProperty(TMP_FOLDER).replace("\", "/");

        if (path_.startsWith(folder_)) {
            //If the jar is located in the temp folder, then delete all previous jars before exit.
            //Begin of my new code
            try {
                for (File f: new File(folder_).listFiles()) {
                    if (!f.getName().toLowerCase().endsWith(".jar")) {
                        continue;
                    }
                    f.delete();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //End of my new code
        }
        //Exit the program
        System.exit(0);
    }
}


感谢 Ferrybig 和 Marged 对我的帮助。