【问题标题】:Java (JGIT) Files.delete() fails to delete a file, but file.delete() succeedsJava (JGIT) Files.delete() 无法删除文件,但 file.delete() 成功
【发布时间】:2017-07-23 14:11:36
【问题描述】:

我正在使用 jgit(版本 4.8.0.201706111038-r)将 git repo 克隆到临时目录中,并添加关闭挂钩以在终止后删除临时目录。但是,关闭挂钩无法从 .git 子目录中删除一些文件(尽管关闭了 Git 对象,根据 jgit 的要求)。

有趣的是,只有当我使用 Path API (Files.delete(<PATH>)) 时删除才会失败,但如果我使用旧的 file.delete() 删除则不会。

这是一个最小的独立示例,其唯一依赖项是 jgit 4.8.0.201706111038-r:

public static void main(String... args) throws Exception {
    String gitRepo = "https://github.com/netgloo/spring-boot-samples.git";
    Path localDir = Files.createTempDirectory(null);

    // Clone repo
    Git git = Git.cloneRepository().setURI(gitRepo).setBranch("master").setDirectory(localDir.toFile()).call();

    // Print some stuff to make sure that the git repo actually works
    for (RevCommit c : git.log().call()) {
        System.out.println(c);
    }

    git.getRepository().close(); // Close all the things!
    git.close(); // Close all the things!

    // Delete
    Files.walkFileTree(localDir, new SimpleFileVisitor<Path>() {
        void safeDelete(Path p) {
            try {
                Files.delete(p);
            } catch (Exception e) {
                try {
                    Files.delete(p);
                } catch (Exception e2) {
                    System.err.println("Failed to delete " + p + " due to " + e.getClass().getSimpleName() + " using Files.detlete().\nTrying toFile().delete(): " + p.toFile().delete());
                }
            }
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            safeDelete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
            safeDelete(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}

输出:

...
Failed to delete C:\Users\malt\AppData\Local\Temp\7908805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.idx due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true
Failed to delete C:\Users\malt\AppData\Local\Temp\7908805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.pack due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true

谁能解释为什么会这样?有没有办法让 JGIT 正确关闭这些文件,以便 Files.delete() 工作?

【问题讨论】:

    标签: java filesystems jgit


    【解决方案1】:

    当从CloneCommand 获得时,单独的Git::close 应该足以释放JGit 为给定存储库持有的所有文件句柄。在这种情况下,它只是委托给Repository::close

    我认为您看到的Files::delete()File::delete() 之间的区别在这里解释:

    Difference between Files#delete(Path) and File#delete()

    可能不相关,但我认为仍然值得一提的是最近引入的 auto-gc 后台线程的问题。它还可能会阻止存储库被成功删除。请参阅此邮件列表线程:

    https://dev.eclipse.org/mhonarc/lists/jgit-dev/msg03370.html

    为了解决后一个问题,我在存储库的配置中禁用了 auto-gc,如下所示:

    StoredConfig config = repository.getConfig();
    config.setBoolean(CONFIG_GC_SECTION, null, CONFIG_KEY_AUTODETACH, false);
    config.setInt(CONFIG_GC_SECTION, null, CONFIG_KEY_AUTOPACKLIMIT, -1);
    config.setInt(CONFIG_GC_SECTION, null, CONFIG_KEY_AUTO, -1);
    config.save();
    

    常量是从ConfigConstants静态导入的。

    这符合你的问题吗?

    【讨论】:

    • 我意识到双重close() 调用是多余的,我只是想为了问题的目的使调用非常明确。关于 GC 配置 - 我已将您提供的代码添加到重现代码中,但我得到了相同的行为。 Files.delete() 与 File.delete() 的解释似乎是正确的。
    • 我在用你的 sn-p 禁用 auto-gc 后也没有看到任何效果,但我认为你可能会遇到这种情况,Files::close vs File::close 问题解决了。跨度>
    • @RüdigerHerrmann 这并不能解决我害怕的问题。在某些邮件列表上关闭存储库后,我已经看到了 2 或 3 个关于锁定文件的案例,但没有找到解决方案。
    • 如果您在最新版本的 JGit 中发现这些问题并且可以重现,您可能需要提交错误。
    【解决方案2】:

    如果有人仍然面临同样的问题,对我有用的是强制调用 gc 以释放文件锁定

    gitReference.gc().call()
    

    这是我的完整关闭方法:

    public void close() {
        if (gitReference != null) {
           try {            
                gitReference.close();           
                gitReference.gc().call();
            } catch (GitAPIException e) {
                throw new RuntimeException(e);
            }
            gitReference = null;
        }
    }
    

    祝你好运

    贾拉尔

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-30
      • 2020-09-19
      • 2015-10-14
      • 1970-01-01
      相关资源
      最近更新 更多