Файл Java исчезает с пути /tmp/hsperfdata_*username*/

Это очень запутанная проблема.

У нас есть Java-приложение (Java8 и работающее на JBoss 6.4), которое зацикливает определенное количество объектов и записывает несколько строк в файл на каждом раунде.

В каждом раунде мы проверяем, получили ли мы объект File в качестве параметра, и если нет, мы создаем новый объект и создаем физический файл:

if (file == null){
   File file = new File(filename);
   try{
        file.createNewFile();
   } catch (IOException e) {e.printStackTrace();}}

Итак, идея в том, что файл создается только один раз, после чего шаг пропускается и мы сразу приступаем к написанию. Переменное имя файла не является путем, это просто имя файла без пути, поэтому файл создается по пути jboss_root/tmp/hsperfdata_имя пользователя/

редактировать1. Я добавлю сюда также методы, используемые при написании, если они имеют отношение к делу:

fw = new FileWriter(indeksiFile, true); // append = true
bw = new BufferedWriter(fw);
out = new PrintWriter(bw);
.
.
out.println(..)
.
.
out.flush();
out.close(); // this flushes as well -> line above is useless

Итак, теперь проблема в том, что иногда, довольно редко, физический файл исчезает из пути в середине процесса. Ссылка на java-объект никогда не теряется, но кажется, что сам объект исчезает, потому что код автоматически создает файл снова по тому же пути и продолжает записывать в него данные. Этого бы не произошло, если бы условие file == null не оценивалось как истинное. Очевидно, что эффект заключается в том, что мы теряем строки, которые были записаны в предыдущий файл. Java-приложение не замечает никаких ошибок и продолжает работать.

Итак, у меня было бы три тесно связанных вопроса, на которые я не смог найти ответ в Google.

  1. Если мы вызовем метод File.CreateNewFile(), будет ли результирующий файл постоянным файлом в файловой системе или каким-то JVM-прокси-файлом?
  2. Если это постоянный файл, вы знаете, почему он исчезает? Поведение по умолчанию в нашем случае таково, что в какой-то момент файл всегда удаляется из пути. Я предполагаю, что тот же механизм удаляет файл слишком рано. Я просто не знаю, как управлять этим механизмом.
  3. Мое лучшее предположение состоит в том, что это связано с этим путем jboss_root/tmp/hsperfdata_имя пользователя/, который является некоторой папкой временных данных, созданной JVM, и, вероятно, есть какое-то поведение по умолчанию, которое очищает путь. Я хоть близко?

Помощь приветствуется! Спасибо!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
530
1

Ответы 1

File.createNewFile Я никогда не использовал в своем коде: это не нужно. При последующей записи в файл он, вероятно, создает его заново или добавляет. В любом случае есть гонка в файловой системе. Кроме того, поскольку это не атомарные действия, вы можете получить что-то нестабильное.

Итак, вы хотите записать в файл, добавив существующий файл или создав его. Для текста UTF-8:

Path path = Paths.get(filename);
try (PrintWriter out = new PrintWriter(
        Files.newBufferedWriter(path, StandardOpenOption.CREATE, StandardOpenOption.APPEND),
            false)) {
    out.println("Killroy was here");
}

После комментария Честно говоря, насколько вы заинтересованы в причине, трудно сказать. Перезапуск приложения или исключения ввода-вывода (?), которые можно найти в журналах. Добавьте ведение журнала в определенный журнал для добавления к файлам и (регистрируемую) периодическую проверку существования этих файлов.


охрана Здесь мы делаем повторный физический доступ к файловой системе.

Чтобы предотвратить добавление к файлу дважды одновременно (из которых я ожидаю исключения), можно создать критическую секцию в той или иной форме.

// For 16 semaphores:
final int semaphoreCount = 16;
final int semaphoreMask = 0xF;
Semaphore[] semaphores = new Semaphore[semaphoreCount];
for (int i = 0; i < semaphores.length; ++i) {
    semaphores[i] = new Semaphore(1, true); // FIFO
}

int hash = filename.hashcode() & semaphoreMask ; // toLowerCase on Windows
Semaphore semaphore = semaphores[hash];
try {
    semaphore.aquire();
    ... append
} finally {
    semaphore.release();
}

Блокировка файлов была бы более техническим решением, которое я бы не хотел предлагать.

Лучшим решением, которое у вас, возможно, уже есть, будет очереди сообщений на файл.

Я уверен, что это, вероятно, очень близко к решению проблемы, но это не помогает мне понять явление, наблюдаемое с текущим решением. В качестве справочной информации: текущее решение уже находится в разработке и работает примерно в 90% случаев (что, безусловно, недостаточно). Я бы очень хотел знать, какой механизм теперь отвечает за исчезновение файла.

Julius Torkkeli 15.03.2019 10:21

Данные могут исчезнуть из-за createNewFile, так как атомарность не гарантируется. То же самое, когда один и тот же файл добавляется одновременно. Одна мера, которую я добавлю к ответу.

Joop Eggen 15.03.2019 10:52

«Перезапуск приложения или исключения ввода-вывода (?) можно найти в журналах. Добавьте ведение журнала в определенный журнал для добавления к файлам и (зарегистрированную) периодическую проверку существования этих файлов». Приложение ничего не замечает, никаких исключений ввода/вывода. И да, мы проверили, что файл сначала создается, затем исчезает, а затем снова создается, регистрируя периодическую проверку. Помните, что createNewFile (по крайней мере, должен) вызываться только один раз. Итак, каков будет механизм, из-за которого файл, который он создал, исчезнет позже? Что вы подразумеваете под добавлением одновременно, кем?

Julius Torkkeli 15.03.2019 21:04

Я имел в виду параллелизм, если более одного потока будут делать то же самое. Или в редком случае при перезапуске приложения (сделав дважды createNewFile). Наиболее вероятной причиной может быть второй createNewFile для имени файла такой же — дубликат имени файла, созданный каким-то образом. Например, с временным шаблоном ччммсс вместо ччммсс; первый - это двенадцатичасовой повторяющийся узор. Также System.currentMillis может не продвигать свой длинный результат. Проще говоря: Не имею представления.

Joop Eggen 19.03.2019 22:23

Другие вопросы по теме