in apm-agent-plugins/apm-profiling-plugin/src/main/java/co/elastic/apm/agent/profiler/asyncprofiler/JfrParser.java [155:253]
private void parseContent() throws IOException {
BufferedFile bufferedFile = this.bufferedFile;
int contentTypeId = bufferedFile.getInt();
logger.debug("Parsing content type {}", contentTypeId);
int count = bufferedFile.getInt();
switch (contentTypeId) {
case ContentTypeId.CONTENT_THREAD:
for (int i = 0; i < count; i++) {
int threadId = bufferedFile.getInt();
String threadName = readUtf8String().toString();
}
break;
case ContentTypeId.CONTENT_JAVA_THREAD:
for (int i = 0; i < count; i++) {
bufferedFile.ensureRemaining(16);
long javaThreadId = bufferedFile.getUnsafeLong();
int nativeThreadId = bufferedFile.getUnsafeInt();
int threadGroup = bufferedFile.getUnsafeInt();
nativeTidToJavaTid.put(nativeThreadId, javaThreadId);
}
break;
case ContentTypeId.CONTENT_THREAD_GROUP:
// no info
break;
case ContentTypeId.CONTENT_STACKTRACE:
for (int i = 0; i < count; i++) {
bufferedFile.ensureRemaining(13);
int pos = (int) bufferedFile.position();
// always an integer
// see profiler.h
// MAX_CALLTRACES = 65536
int stackTraceKey = (int) bufferedFile.getUnsafeLong();
this.stackTraceIdToFilePositions.put(stackTraceKey, pos);
bufferedFile.getUnsafe(); // truncated
int numFrames = bufferedFile.getUnsafeInt();
int sizeOfFrame = 13;
bufferedFile.skip(numFrames * sizeOfFrame);
}
break;
case ContentTypeId.CONTENT_CLASS:
for (int i = 0; i < count; i++) {
bufferedFile.ensureRemaining(26);
// classId is an incrementing integer, no way there are more than 2 billion distinct ones
int classId = (int) bufferedFile.getUnsafeLong();
bufferedFile.getUnsafeLong(); // loader class
// symbol ids are incrementing integers, no way there are more than 2 billion distinct ones
int classNameSymbolId = (int) bufferedFile.getUnsafeLong();
classIdToClassNameSymbolId.put(classId, classNameSymbolId); // class name
bufferedFile.getUnsafeShort(); // access flags
}
break;
case ContentTypeId.CONTENT_METHOD:
for (int i = 1; i <= count; i++) {
bufferedFile.ensureRemaining(35);
long id = bufferedFile.getUnsafeLong();
// classId is an incrementing integer, no way there are more than 2 billion distinct ones
int classId = (int) bufferedFile.getUnsafeLong();
// symbol ids are incrementing integers, no way there are more than 2 billion distinct ones
int methodNameSymbolId = (int) bufferedFile.getUnsafeLong();
frameIdToFrame.put(id, FRAME_NULL);
frameIdToClassId.put(id, classId);
frameIdToMethodSymbol.put(id, methodNameSymbolId);
bufferedFile.getUnsafeLong(); // signature
bufferedFile.getUnsafeShort(); // modifiers
bufferedFile.getUnsafe(); // hidden
}
break;
case ContentTypeId.CONTENT_SYMBOL:
for (int i = 0; i < count; i++) {
// symbol ids are incrementing integers, no way there are more than 2 billion distinct ones
int symbolId = (int) bufferedFile.getLong();
int pos = (int) bufferedFile.position();
symbolIdToPos.put(symbolId, pos);
symbolIdToString.put(symbolId, SYMBOL_NULL);
skipString();
}
break;
case ContentTypeId.CONTENT_STATE:
// we're not really interested in the thread states
// but we sill have to consume the bytes
for (int i = 1; i <= count; i++) {
bufferedFile.getShort();
skipString();
}
break;
case ContentTypeId.CONTENT_FRAME_TYPE:
isJavaFrameType = new boolean[count + 1];
for (int i = 1; i <= count; i++) {
int id = bufferedFile.get();
if (i != id) {
throw new IllegalStateException("Expecting ids to be incrementing");
}
isJavaFrameType[id] = JAVA_FRAME_TYPES.contains(readUtf8String().toString());
}
break;
default:
throw new IOException("Unknown content type " + contentTypeId);
}
}