Java Flight Recorder (JFR) из командной строки: [jfr] [ERROR] [1014.291] Репозиторий не может быть удален при завершении работы

Я прохожу курс по использованию Java Flight Recorder java-flight-recorder-monitoring.

Я скомпилировал java-код из примера (добавив class и imports, потому что он не компилировался без них):

import java.util.ArrayList;
import java.util.List;

class TestFlightRecorder {
public static void main(String[] args) {
    List<Object> items = new ArrayList<>(1);
    try {
        while (true){
            items.add(new Object());
        }
    } catch (OutOfMemoryError e){
        System.out.println(e.getMessage());
    }
    assert items.size() > 0;
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        System.out.println(e.getMessage());
    }
}
}

Потом бегаю по курсу:

C: \ Program Files \ Java \ jdk1.8.0_191 \ bin> java -XX: + UnlockCommercialFeatures -XX: + F lightRecorder -XX: StartFlightRecording = duration = 200s, filename = c: \ am \ out \ flight.j fr - cp c: \ am \ out TestFlightRecorder

Вывод сразу после:

Началась запись 1. Результат будет записан в:

C: \ AM \ out \ flight.jfr

Использование памяти в диспетчере задач Windows для java увеличивается, а затем спустя более 200 секунд:

Исключение в потоке "main" java.lang.OutOfMemoryError: пространство кучи Java в TestFlightRecorder.main (TestFlightRecorder.java:12) [jfr] [ERROR] [1014.291] Репозиторий не может быть удален при завершении работы

И результирующий flight.jfr имеет размер 0 байт. (когда я сделал ту же команду с простым java-классом hello world, был создан flight.jfr размером 125 КБ с «пустой» информацией внутри - я думаю, это связано с тем, что приложение работало так быстро, запись полета еще не началась - и это вопрос не в этой пустоте).

Поиск такой ошибки в Интернете не дал результатов. Почему ошибка, я что-то сделал неправильно, чтобы сделать запись?


person Alexei Martianov    schedule 29.08.2019    source источник
comment
Разве ваш Thread.sleep не должен быть внутри while(true) цикла? Поскольку это ваш код, он устремится к ошибке OOMError, которая, вероятно, нарушит работу JVM настолько, что регистратор полетов не сможет записать пустую информацию в свой файл журнала, отображая ошибку, которую вы видели.   -  person Aaron    schedule 29.08.2019
comment
@Aaron, «пустая информация» может не иметь отношения, я написал об этом, чтобы показать, что jfr обычно работает на этой рабочей станции. Что касается OOM, конечно, сказано, что ошибка является частью идеи приложения. Наша программа вставляет объекты в список до тех пор, пока не произойдет OutOfMemoryError. Если мы просто переместим сон внутрь цикла, насколько я понял, память будет расти слишком медленно для обучающего упражнения.   -  person Alexei Martianov    schedule 29.08.2019
comment
Вы уже знаете, какой результат ожидается? Поскольку в противном случае обнаружение OOM приводит к сбою FlightRecorder, кажется, что это могло быть ожидаемым выводом.   -  person Aaron    schedule 29.08.2019
comment
На самом деле я не могу воспроизвести вашу проблему, каждый раз, когда я запускаю ваш код, я получаю данные записи полета, вероятно, из-за разных настроек памяти. Тем не менее, я могу предложить вам удалить catch и thread.sleep, наличия только init списка и цикла while(true) достаточно, чтобы удовлетворить ваши требования, и наличие 1-секундного ожидания, в течение которого список все еще находится в области видимости, вероятно, ухудшит ситуация.   -  person Aaron    schedule 29.08.2019
comment
@Aaron, спасибо за ваш вклад в OOMError, который, вероятно, нарушает работу JVM настолько, что FlightRecorder не может писать, я запустил код с настройкой на 20 секунд и получил результирующую запись с графиками, похожими на курс. Так что считаю текущий вопрос решенным.   -  person Alexei Martianov    schedule 29.08.2019


Ответы (2)


Java Flight Recorder записывает дамп в обработчике завершения работы Java, когда приложение завершается. Если памяти недостаточно для создания дампа, произойдет сбой.

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

person Kire Haglin    schedule 30.08.2019
comment
В моей команде jfr был установлен на таймфрейм 200 секунд. Вы пишете о случае закрытия приложения. Я не мог понять, как применим ваш ответ. - person Alexei Martianov; 02.09.2019
comment
Если вы сделаете запись с продолжительностью, дамп будет создан при завершении приложения, что, как я предполагал, произошло, когда приложение исчерпало память. - person Kire Haglin; 02.09.2019
comment
В общем, в среде с низким объемом памяти многие вещи могут пойти не так в коде JFR, написанном на Java. JFR создает по крайней мере два других потока, которые также выделяют память, и если они запустят OOME перед основным потоком, все сломается. - person Kire Haglin; 02.09.2019

На что указывает комментарий Аарона:

OOMError, которая, вероятно, нарушает работу JVM настолько, что регистратор полетов не может записать

Я запустил код со временем перекодирования 20 с, а не 200 с (в диспетчере задач я заметил, что использование памяти Java выросло до максимальной кучи 2 ГБ примерно за это время) и получил результирующую запись с графиками, аналогичными представленным в курсе. Так что считаю текущий вопрос решенным.

person Alexei Martianov    schedule 29.08.2019