Skip to content

Instantly share code, notes, and snippets.

@aumgn
Last active May 18, 2018 08:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aumgn/3e3c5c73f71adef08cc1fbdb9974979c to your computer and use it in GitHub Desktop.
Save aumgn/3e3c5c73f71adef08cc1fbdb9974979c to your computer and use it in GitHub Desktop.
JfrAllocStackCollapse: Takes a JFR (Java Flight Recorder) recording and generate a "stack-collapse'd" text file consumable by a FlameGraph

Compile java class :

MCVERSION=5.5.1.172852
MCCP=$JAVA_HOME/lib/missioncontrol/plugins/com.jrockit.mc.common_$MCVERSION.jar:$JAVA_HOME/lib/missioncontrol/plugins/com.jrockit.mc.flightrecorder_$MCVERSION.jar
javac -cp $MCCP JfrAllocStackCollapse.java

Perform recording with :

jcmd <pid> JFR.start settings=<path-to>/alloc.jfc compress=true duration=30s filename=alloc.jfr

Generate stack-collapse'd file with :

MCVERSION=5.5.1.172852
MCCP=$JAVA_HOME/lib/missioncontrol/plugins/com.jrockit.mc.common_$MCVERSION.jar:$JAVA_HOME/lib/missioncontrol/plugins/com.jrockit.mc.flightrecorder_$MCVERSION.jar
java -cp .:$MCCP JfrAllocStackCollapse alloc.jfr >alloc.stacks

Generate flamegraph :

flamegraph.pl --countname "Bytes" alloc.stacks >alloc.svg
<?xml version="1.0" encoding="UTF-8"?>
<configuration version="1.0" name="Alloc" description="Only profile memory allocations, meant for memory pressure FlameGraph" provider="Oracle">
<producer uri="http://www.oracle.com/hotspot/jvm/" label="Oracle JDK">
<event path="java/statistics/thread_allocation">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="java/statistics/class_loading">
<setting name="enabled">false</setting>
<setting name="period">1000 ms</setting>
</event>
<event path="java/statistics/threads">
<setting name="enabled">false</setting>
<setting name="period">1000 ms</setting>
</event>
<event path="java/thread_start">
<setting name="enabled">false</setting>
</event>
<event path="java/thread_end">
<setting name="enabled">false</setting>
</event>
<event path="java/thread_sleep">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="java/thread_park">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="java/monitor_enter">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="java/monitor_wait">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="vm/class/load">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/class/unload">
<setting name="enabled">false</setting>
</event>
<event path="vm/info">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/initial_system_property">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/prof/execution_sample">
<setting name="enabled">false</setting>
<setting name="period">999 d</setting>
</event>
<event path="vm/prof/execution_sampling_info">
<setting name="enabled">false</setting>
<setting name="threshold">1 ms</setting>
</event>
<event path="vm/runtime/execute_vm_operation">
<setting name="enabled">false</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="vm/runtime/thread_dump">
<setting name="enabled">false</setting>
<setting name="period">999 d</setting>
</event>
<event path="vm/flag/long">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/flag/ulong">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/flag/double">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/flag/boolean">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/flag/string">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/flag/long_changed">
<setting name="enabled">false</setting>
</event>
<event path="vm/flag/ulong_changed">
<setting name="enabled">false</setting>
</event>
<event path="vm/flag/double_changed">
<setting name="enabled">false</setting>
</event>
<event path="vm/flag/boolean_changed">
<setting name="enabled">false</setting>
</event>
<event path="vm/flag/string_changed">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/detailed/object_count">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/gc/configuration/gc">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/gc/configuration/heap">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/gc/configuration/young_generation">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/gc/configuration/tlab">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/gc/configuration/survivor">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/gc/detailed/object_count_after_gc">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/heap/summary">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/heap/ps_summary">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/heap/metaspace_summary">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/metaspace/gc_threshold">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/metaspace/allocation_failure">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>
<event path="vm/gc/metaspace/out_of_memory">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>
<event path="vm/gc/metaspace/chunk_free_list_summary">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/collector/garbage_collection">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/collector/parold_garbage_collection">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/collector/young_garbage_collection">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/collector/old_garbage_collection">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/collector/g1_garbage_collection">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/phases/pause">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/phases/pause_level_1">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/phases/pause_level_2">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/phases/pause_level_3">
<setting name="enabled">false</setting>
<setting name="threshold">0 ms</setting>
</event>
<event path="vm/gc/reference/statistics">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/detailed/promotion_failed">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/detailed/evacuation_failed">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/detailed/evacuation_info">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/detailed/concurrent_mode_failure">
<setting name="enabled">false</setting>
</event>
<event path="vm/gc/detailed/allocation_requiring_gc">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>
<event path="vm/compiler/config">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/compiler/stats">
<setting name="enabled">false</setting>
<setting name="period">1000 ms</setting>
</event>
<event path="vm/compiler/compilation">
<setting name="enabled">false</setting>
<setting name="threshold">100 ms</setting>
</event>
<event path="vm/compiler/phase">
<setting name="enabled">false</setting>
<setting name="threshold">10 s</setting>
</event>
<event path="vm/compiler/failure">
<setting name="enabled">false</setting>
</event>
<event path="vm/code_sweeper/config">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/code_sweeper/stats">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/code_sweeper/sweep">
<setting name="enabled">false</setting>
<setting name="threshold">100 ms</setting>
</event>
<event path="vm/code_cache/config">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/code_cache/stats">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="vm/code_cache/full">
<setting name="enabled">false</setting>
</event>
<event path="os/information">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="os/processor/cpu_information">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="os/processor/context_switch_rate">
<setting name="enabled">false</setting>
<setting name="period">10 s</setting>
</event>
<event path="os/processor/cpu_load">
<setting name="enabled">false</setting>
<setting name="period">1000 ms</setting>
</event>
<event path="os/processor/cpu_tsc">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="os/system_process">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="os/initial_environment_variable">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="os/memory/physical_memory">
<setting name="enabled">false</setting>
<setting name="period">everyChunk</setting>
</event>
<event path="java/object_alloc_in_new_TLAB">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>
<event path="java/object_alloc_outside_TLAB">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>
</producer>
<producer uri="http://www.oracle.com/hotspot/jdk/" label="Oracle JDK">
<event path="java/file_read">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="java/file_write">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="java/socket_read">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="java/socket_write">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold">10 ms</setting>
</event>
<event path="java/exception_throw">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>
<event path="java/error_throw">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>
<event path="java/statistics/throwables">
<setting name="enabled">false</setting>
<setting name="period">1000 ms</setting>
</event>
</producer>
<producer uri="http://www.oracle.com/hotspot/jfr-info/" label="Oracle JDK">
<event path="recordings/recording">
<setting name="enabled">true</setting>
</event>
<event path="recordings/recording_setting">
<setting name="enabled">true</setting>
</event>
</producer>
</configuration>
import com.jrockit.mc.common.IMCFrame;
import com.jrockit.mc.common.IMCMethod;
import com.jrockit.mc.flightrecorder.FlightRecording;
import com.jrockit.mc.flightrecorder.FlightRecordingLoader;
import com.jrockit.mc.flightrecorder.internal.model.FLRStackTrace;
import com.jrockit.mc.flightrecorder.spi.IEvent;
import java.io.*;
import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipException;
public class JfrAllocStackCollapse {
public static void main(String[] args) throws IOException {
String inputPath = args[0];
run(inputPath);
}
private static void run(String inputPath) throws IOException {
FlightRecording frl;
try (InputStream input = new FileInputStream(inputPath);
GZIPInputStream gzipInput = new GZIPInputStream(input)) {
frl = FlightRecordingLoader.loadStream(gzipInput);
}
catch (ZipException exc) {
frl = FlightRecordingLoader.loadFile(new File(inputPath));
}
try (Writer output = new OutputStreamWriter(System.out)) {
for (IEvent event : frl.createView()) {
if (!event.getEventType().getPath().startsWith("java/object_alloc")) {
continue;
}
boolean newTLAB = event.getEventType().getPath().equals("java/object_alloc_in_new_TLAB");
FLRStackTrace flrTrace = (FLRStackTrace) event.getValue("(stackTrace)");
if (flrTrace == null) {
continue;
}
output.write(event.getEventType().getPath());
List<? extends IMCFrame> frames = flrTrace.getFrames();
for(int i = frames.size() - 1; i >= 0; i--) {
IMCFrame frame = frames.get(i);
IMCMethod method = frame.getMethod();
output.write(";");
output.write(method.getPackageName());
output.write(".");
output.write(method.getClassName());
output.write("#");
output.write(method.getMethodName());
}
output.write(";");
writetype(output, event.getValue("class").toString());
output.write(" ");
output.write(event.getValue(newTLAB ? "tlabSize" : "allocationSize").toString());
output.write("\n");
}
}
}
private static void writetype(Writer output, String type) throws IOException {
if (!type.startsWith("[")) {
output.write(type);
return;
}
String subtype = type.substring(1);
switch (subtype.charAt(0)) {
case 'Z':
output.write("boolean");
break;
case 'B':
output.write("byte");
break;
case 'S':
output.write("short");
break;
case 'I':
output.write("int");
break;
case 'J':
output.write("long");
break;
case 'F':
output.write("float");
break;
case 'D':
output.write("double");
break;
case 'C':
output.write("char");
break;
case 'L':
case '[':
writetype(output, subtype);
break;
default:
throw new RuntimeException();
}
output.write("[]");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment