1. Información general
En este tutorial, examinaremos Java Flight Recorder, sus conceptos, sus comandos básicos y cómo usarlo.
2. Utilidades de supervisión de Java
Java no es solo un lenguaje de programación, sino un ecosistema muy rico con muchas herramientas. El JDK contiene programas que nos permiten compilar nuestros propios programas, así como monitorear su estado y el estado de la Máquina Virtual Java durante el ciclo de vida completo de ejecución del programa.
La carpeta bin de una distribución JDK contiene, entre otros, los siguientes programas que se pueden utilizar para crear perfiles y supervisar:
- Java VisualVM (jvisualvm.exe)
- JConsole (jconsole.exe)
- Control de misión de Java (jmc.exe)
- Herramienta de comando de diagnóstico (jcmd.exe)
Sugerimos explorar el contenido de esta carpeta para estar al tanto de las herramientas que tenemos a nuestra disposición. Tenga en cuenta que Java VisualVM formaba parte de las distribuciones Oracle y Open JDK en el pasado. Sin embargo, a partir de Java 9, las distribuciones JDK ya no se envían con Java VisualVM . Por lo tanto, deberíamos descargarlo por separado del sitio web del proyecto de código abierto VisualVM.
En este tutorial, nos centraremos en Java Flight Recorder. Esto no está presente entre las herramientas mencionadas anteriormente porque no es un programa independiente. Su uso está estrechamente relacionado con dos de las herramientas anteriores: Java Mission Control y Diagnostic Command Tools.
3. Java Flight Recorder y sus conceptos básicos
Java Flight Recorder (JFR) es una herramienta de monitoreo que recopila información sobre los eventos en una máquina virtual Java (JVM) durante la ejecución de una aplicación Java . JFR es parte de la distribución JDK y está integrado en la JVM.
JFR está diseñado para afectar el rendimiento de una aplicación en ejecución lo menos posible .
Para utilizar JFR, debemos activarlo. Podemos lograr esto de dos maneras:
- al iniciar una aplicación Java
- pasar comandos de diagnóstico de la herramienta jcmd cuando ya se está ejecutando una aplicación Java
JFR no tiene una herramienta independiente. Utilizamos Java Mission Control (JMC), que contiene un complemento que nos permite visualizar los datos recopilados por JFR.
Estos tres componentes, JFR , jcmd y JMC , forman una suite completa para recopilar información de tiempo de ejecución de bajo nivel de un programa Java en ejecución. Podemos encontrar esta información muy útil a la hora de optimizar nuestro programa, o al diagnosticarlo cuando algo sale mal.
Si tenemos varias versiones de Java instaladas en nuestra computadora, es importante asegurarse de que el compilador de Java ( javac ), el lanzador de Java ( java ) y las herramientas mencionadas anteriormente (JFR, jcmd y JMC) sean de la misma distribución de Java. . De lo contrario, existe el riesgo de no poder ver ningún dato útil porque los formatos de datos JFR de diferentes versiones pueden no ser compatibles.
JFR tiene dos conceptos principales: eventos y flujo de datos. Discutamos brevemente sobre ellos.
3.1. Eventos
JFR recopila eventos que ocurren en la JVM cuando se ejecuta la aplicación Java. Estos eventos están relacionados con el estado de la propia JVM o el estado del programa. Un evento tiene un nombre, una marca de tiempo e información adicional (como información de subprocesos, pila de ejecución y estado del montón).
Hay tres tipos de eventos que recopila JFR:
- un evento instantáneo se registra inmediatamente una vez que ocurre
- un evento de duración se registra si su duración supera un umbral especificado
- un evento de muestra se utiliza para muestrear la actividad del sistema
3.2. Flujo de datos
Los eventos que recopila JFR contienen una gran cantidad de datos. Por esta razón, por diseño, JFR es lo suficientemente rápido como para no obstaculizar el programa.
JFR guarda datos sobre los eventos en un único archivo de salida, flight.jfr.
Como sabemos, las operaciones de E / S de disco son bastante caras. Por lo tanto, JFR utiliza varios búferes para almacenar los datos recopilados antes de descargar los bloques de datos en el disco. Las cosas pueden volverse un poco más complejas porque, al mismo tiempo, un programa puede tener múltiples procesos de registro con diferentes opciones.
Debido a esto, es posible que encontremos más datos en el archivo de salida de los solicitados o puede que no estén en orden cronológico . Es posible que ni siquiera notemos este hecho si usamos JMC, porque visualiza los eventos en orden cronológico.
En algunos casos raros, JFR puede fallar al vaciar los datos (por ejemplo, cuando hay demasiados eventos o en el caso de un corte de energía). Si esto ocurre, JFR intenta informarnos que al archivo de salida le pueden faltar algunos datos.
4. Cómo utilizar Java Flight Recorder
JFR es una función experimental, por lo que su uso está sujeto a cambios. De hecho, en distribuciones anteriores, tenemos que activar características comerciales para poder usarlo en producción. Sin embargo, a partir de JDK 11, podemos usarlo sin activar nada. Siempre podemos consultar las notas de la versión oficial de Java para comprobar cómo utilizar esta herramienta.
Para JDK 8, para poder activar JFR, debemos iniciar la JVM con las opciones + UnlockCommercialFeatures y + FlightRecorder .
Como mencionamos anteriormente, hay dos formas de activar JFR. Cuando lo activamos simultáneamente con el inicio de la aplicación, lo hacemos desde la línea de comandos. Cuando la aplicación ya se está ejecutando, usamos la herramienta de comando de diagnóstico.
4.1. Línea de comando
Primero, compilamos el archivo * .java del programa en un * .class usando el compilador java estándar javac .
Una vez que la compilación sea exitosa, podemos iniciar el programa con las siguientes opciones:
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=200s,filename=flight.jfr path-to-class-file
donde path-to-class-file es el punto de entrada de la aplicación * .class file.
This command launches the application and activates the recording, which starts immediately and lasts no more than 200 seconds. Collected data is saved in an output file, flight.jfr. We'll describe the other options in more detail in the next section.
4.2. Diagnostic Command Tool
We can also start registering the events by using the jcmd tool. For example:
jcmd 1234 JFR.start duration=100s filename=flight.jfr
Prior to JDK 11, in order to be able to activate JFR in this way, we should start the application with unlocked commercial features:
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -cp ./out/ com.baeldung.Main
Once the application is running, we use its process id in order to execute various commands, which take the following format:
jcmd [parameters]
Here's a complete list of the diagnostic commands:
- JFR.start – starts a new JFR recording
- JFR.check – checks running JFR recording(s)
- JFR.stop – stops a specific JFR recording
- JFR.dump – copies contents of a JFR recording to file
Each command has a series of parameters. For example, the JFR.start command has the following parameters:
- name – the name of the recording; it serves to be able to reference this recording later with other commands
- delay – dimensional parameter for a time delay of recording start, the default value is 0s
- duration – dimensional parameter for a time interval of the duration of the recording; the default value is 0s, which means unlimited
- filename – the name of a file that contains the collected data
- maxage – dimensional parameter for the maximum age of collected data; the default value is 0s, which means unlimited
- maxsize – the maximum size of buffers for collected data in bytes; the default value is 0, which means no max size
We've already seen an example of the usage of these parameters at the beginning of this section. For the complete list of the parameters, we may always consult the Java Flight Recorded official documentation.
Although JFR is designed to have as little of a footprint as possible on the performance of the JVM and the application, it's better to limit the maximum amount of collected data by setting at least one of the parameters: duration, maxage, or maxsize.
5. Java Flight Recorder in Action
Let's now demonstrate JFR in action by using an example program.
5.1. Example Program
Our program inserts objects into a list until an OutOfMemoryError occurs. Then the program sleeps for one second:
public static void main(String[] args) { List 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()); } }
Without executing this code, we can spot a potential drawback: the while loop will lead to high CPU and memory usage. Let's use JFR to see these drawbacks and probably find others.
5.2. Start Registering
First, we compile our program by executing the following command from the command line:
javac -d out -sourcepath src/main src/main/com/baeldung/flightrecorder/FlightRecorder.java
At this point, we should find a file FlightRecorder.class in the out/com/baeldung/flightrecorder directory.
Now, we'll start the program with the following options:
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=200s,filename=flight.jfr -cp ./out/ com.baeldung.flightrecorder.FlightRecorder
5.3. Visualize Data
Now, we feed the file flight.jfr to Java Mission Control, which is part of the JDK distribution. It helps us visualize the data about our events in a nice and intuitive way.
Its main screen shows us the information about how the program was using the CPU during its execution. We see that the CPU was loaded heavily, which is quite expected due to the while loop:

On the left side of the view, we see sections General, Memory, Code, and Threads, among others. Each section contains various tabs with detailed information. For example, tab Hot Methods of section Code contains the statistics of method calls:

In this tab, we can spot another drawback of our example program: method java.util.ArrayList.grow(int) has been called 17 times in order to enlarge the array capacity every time there wasn't enough space for adding an object.
In more realistic programs, we may see a lot of other useful information:
- statistics about created objects, when they were created and destroyed by the garbage collector
- a detailed report about the threads' chronology, when they were locked or active
- which I/O operations the application was executing
6. Conclusion
In this article, we introduced the topic of monitoring and profiling a Java application using Java Flight Recorder. This tool remains an experimental one, so we should consult its official site for more complete and recent information.
Como siempre, el fragmento de código está disponible en nuestro repositorio de Github.