Skip to content

Commit

Permalink
Add JFR ThreadDump and NativeLibrary support
Browse files Browse the repository at this point in the history
Note that NativeLibrary is only supported on Linux at this moment.

Signed-off-by: Gengchen Tuo <[email protected]>
  • Loading branch information
thallium committed Nov 5, 2024
1 parent 33c0833 commit 3ff809a
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 0 deletions.
83 changes: 83 additions & 0 deletions runtime/vm/JFRChunkWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

#if defined(J9VM_OPT_JFR)

#if defined(LINUX)
#include <link.h>
#endif /* defined(LINUX) */

#include "JFRChunkWriter.hpp"
#include "JFRConstantPoolTypes.hpp"

Expand Down Expand Up @@ -815,4 +819,83 @@ VM_JFRChunkWriter::writeInitialSystemPropertyEvents(J9JavaVM *vm)
}
}

U_8 *
VM_JFRChunkWriter::writeThreadDumpEvent()
{
/* reserve size field */
U_8 *dataStart = _bufferWriter->getAndIncCursor(sizeof(U_32));

_bufferWriter->writeLEB128(ThreadDumpID);

/* write start time */
_bufferWriter->writeLEB128(j9time_current_time_millis());

char *result = (char *)j9mem_allocate_memory(sizeof(char) * THREAD_DUMP_EVENT_SIZE, OMRMEM_CATEGORY_VM);

if (NULL != result) {
J9VMThread *walkThread = J9_LINKED_LIST_START_DO(_vm->mainThread);
UDATA numThreads = 0;
char *cursor = result;

while (NULL != walkThread) {
UDATA javaTID = J9VMJAVALANGTHREAD_TID(_currentThread, walkThread->threadObject);
UDATA osTID = ((J9AbstractThread *)walkThread->osThread)->tid;
cursor += sprintf(cursor, "%p javaTID: %zd osTID: %zd\n", walkThread, javaTID, osTID);
numThreads++;
walkThread = J9_LINKED_LIST_NEXT_DO(_vm->mainThread, walkThread);
}
sprintf(cursor, "Number of threads: %zd", numThreads);
}

/* write result */
writeStringLiteral(result);

/* write size */
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);

j9mem_free_memory(result);

return dataStart;
}

void
VM_JFRChunkWriter::writeNativeLibraryEvents()
{
#if defined(LINUX)
auto dlIterateCallback = [](struct dl_phdr_info *info, size_t size, void *data) -> int {
if (NULL == info->dlpi_name || info->dlpi_name[0] == '\0') {
return 0;
}

UDATA baseAddress = 0;
UDATA topAddress = 0;

for (int i = 0; i < info->dlpi_phnum; i++) {
const ElfW(Phdr) *phdr = info->dlpi_phdr + i;
if (PT_LOAD == phdr->p_type) {
UDATA phdrBase = info->dlpi_addr + phdr->p_vaddr;
UDATA phdrTop = phdrBase + phdr->p_memsz;

if (0 == baseAddress || phdrBase < baseAddress) {
baseAddress = phdrBase;
}

if (0 == topAddress || phdrTop > topAddress) {
topAddress = phdrTop;
}
}
}

VM_JFRChunkWriter *chunkWriter = (VM_JFRChunkWriter *)data;
chunkWriter->writeNativeLibraryEvent(baseAddress, topAddress, info->dlpi_name);

return 0;
};

dl_iterate_phdr(dlIterateCallback, this);
#endif /* defined(LINUX) */

/* TODO: add implementations for other platforms */
}

#endif /* defined(J9VM_OPT_JFR) */
36 changes: 36 additions & 0 deletions runtime/vm/JFRChunkWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ enum MetadataTypeID {
CPUInformationID = 92,
PhysicalMemoryID = 107,
ExecutionSampleID = 108,
ThreadDumpID = 110,
NativeLibraryID = 111,
ThreadID = 163,
ThreadGroupID = 164,
ClassID = 165,
Expand Down Expand Up @@ -156,6 +158,8 @@ class VM_JFRChunkWriter {
static constexpr int CPU_INFORMATION_EVENT_SIZE = 600;
static constexpr int OS_INFORMATION_EVENT_SIZE = 100;
static constexpr int INITIAL_SYSTEM_PROPERTY_EVENT_SIZE = 6000;
static constexpr int THREAD_DUMP_EVENT_SIZE = 3000;
static constexpr int NATIVE_LIBRARY_EVENT_SIZE = 3000;

static constexpr int METADATA_ID = 1;

Expand Down Expand Up @@ -341,6 +345,10 @@ class VM_JFRChunkWriter {

writePhysicalMemoryEvent();

writeThreadDumpEvent();

writeNativeLibraryEvents();

writeJFRHeader();

if (isResultNotOKay()) {
Expand Down Expand Up @@ -525,6 +533,25 @@ class VM_JFRChunkWriter {
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
}

void
writeNativeLibraryEvent(UDATA baseAddress, UDATA topAddress, const char *name)
{
/* reserve size field */
U_8 *dataStart = _bufferWriter->getAndIncCursor(sizeof(U_32));

_bufferWriter->writeLEB128(NativeLibraryID);

/* write start time */
_bufferWriter->writeLEB128(j9time_current_time_millis());

writeStringLiteral(name);

_bufferWriter->writeLEB128(baseAddress);
_bufferWriter->writeLEB128(topAddress);
/* write size */
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
}

void
writeJFRChunkToFile()
{
Expand Down Expand Up @@ -587,6 +614,10 @@ class VM_JFRChunkWriter {

U_8 *writeOSInformationEvent();

U_8 *writeThreadDumpEvent();

void writeNativeLibraryEvents();

void writeInitialSystemPropertyEvents(J9JavaVM *vm);

UDATA
Expand Down Expand Up @@ -638,6 +669,11 @@ class VM_JFRChunkWriter {
requireBufferSize += CPU_INFORMATION_EVENT_SIZE;

requireBufferSize += INITIAL_SYSTEM_PROPERTY_EVENT_SIZE;

requireBufferSize += THREAD_DUMP_EVENT_SIZE;

requireBufferSize += NATIVE_LIBRARY_EVENT_SIZE;

return requireBufferSize;
}

Expand Down

0 comments on commit 3ff809a

Please sign in to comment.