Реализация Java File.renameTo () для UnixFileSystem - PullRequest
0 голосов
/ 06 июня 2019

Я пытался понять, как File.renameTo() работает в Java, и я достиг следующего метода в UnixFileSystem.java (я на macOS).

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

Я понимаю, что (пожалуйста, исправьте, если яя не прав) native означает, что JVM вызывает код / ​​библиотеку, написанную на другом языке.Итак, где / как я могу или, если возможно, увидеть его реализацию?

Мне любопытно увидеть его реализацию, чтобы подтвердить, могу ли я использовать его для моего следующего варианта использования.

Iнеобходимо запустить приложение Java на двух (или более) разных серверах, которые опрашивают файлы в одном и том же каталоге (общая файловая система), и только один экземпляр (сервер) должен обрабатывать определенный файл.Всякий раз, когда приложение на каком-либо из серверов видит файл, оно пытается перейти в какой-либо другой каталог, и, если перемещение прошло успешно (определяется логическим , возвращенным методом File.renameTo()), этот сервер начинает обработку на этихсодержимое файла (точная пакетная обработка).Я провел быстрый тест с тремя различными экземплярами, опрашивающими один каталог (генерируя новые файлы со скоростью 1000 файлов в секунду), и результаты были такими, как ожидалось.Я просто хочу подтвердить, масштабируется ли он.

Обратите внимание, что я не перемещаю реальный файл, а файл с нулевым байтом, который называется что-то вроде <actual-filename>.DONE, который создается после завершения копирования файла из источника.

1 Ответ

2 голосов
/ 06 июня 2019

AFAIK, Источник OpenJDK и Orale JDK практически одинаков . Следовательно, вы можете найти реализацию rename0 здесь :

#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, здесь документ :

Одна полезная особенность переименования состоит в том, что значение нового имени «атомарно» изменяется от любого ранее существующего файла с этим именем на его новое значение (то есть файл, который назывался старым именем). Нет момента, когда новое имя не существует «между» старым значением и новым значением. Если во время операции происходит сбой системы, оба имени могут существовать; но newname всегда будет без изменений, если оно вообще существует.

Возможно, ваш код безопасен, если он не падает, а файловая система работает нормально. Однако это может зависеть от того, какую файловую систему вы используете (например, nfs).

Есть хороший вопрос в stackoverflow, поэтому он может помочь.

...