UnixFileSystem的Java File.renameTo()实现

时间:2019-06-06 06:50:40

标签: java unix filesystems nio

我试图弄清楚File.renameTo()在Java中的工作方式,并且在UnixFileSystem.java中达到了以下方法(我在macOS上)。

private native boolean rename0(File f1, File f2);

我理解(如果我错了,请更正)native表示JVM调用用另一种语言编写的代码/库。那么,我在哪里/如何或者有可能看到其实现?

我很好奇看到它的实现是为了确认是否可以在以下用例中使用它。

我需要在两个(或多个)不同的服务器中运行Java应用程序,这些服务器轮询同一目录(共享文件系统)中的文件,并且只有一个实例(服务器)应处理特定文件。每当任何服务器上的应用程序看到文件时,它都会尝试移至其他目录,并且如果移动成功(由File.renameTo()方法返回的 boolean 确定),则该服务器将启动对这些文件内容进行处理(准确地说是批处理)。我对三个不同的实例轮询了一个目录(以每秒1000个文件的速度生成新文件)进行了快速测试,结果符合预期。我只想确认它是否可以缩放。

请注意,我并没有移动实际文件,而是移动了从源复制文件后创建的名为<actual-filename>.DONE之类的零字节文件。

1 个答案:

答案 0 :(得分:2)

AFAIK,Source of OpenJDK and Orale JDK are almost the same。 因此,您可以找到rename0 here的实现:

#include <stdlib.h>

JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_rename0(JNIEnv *env, jobject this,
                                    jobject from, jobject to)
{
    jboolean rv = JNI_FALSE;

    WITH_FIELD_PLATFORM_STRING(env, from, ids.path, fromPath) {
        WITH_FIELD_PLATFORM_STRING(env, to, ids.path, toPath) {
            if (rename(fromPath, toPath) == 0) {
                rv = JNI_TRUE;
            }
        } END_PLATFORM_STRING(env, toPath);
    } END_PLATFORM_STRING(env, fromPath);
    return rv;
}

您可以看到它实际上是在调用libc的rename。 由于大多数环境使用glibc,因此here是文档:

  

重命名的一个有用的功能是,新名称的含义从原子上从以前存在的任何文件“原子地”更改为它的新含义(即称为旧名称的文件)。在旧含义和新含义之间没有“新名称”不存在的瞬间。如果操作过程中发生系统崩溃,则两个名称可能仍然存在;但是newname只要存在就永远是完整的。

也许您的代码只要不崩溃就可以安全使用,并且文件系统可以正常工作。但是,这可能取决于您所使用的文件系统(例如nfs)。

There's good another question在stackoverflow中,所以可能有帮助。