Skip to content
Permalink
Browse files

8237499: JFR: Include stack trace in the ThreadStart event

Reviewed-by: egahlin
  • Loading branch information
Denghui Dong
Denghui Dong committed Feb 24, 2020
1 parent 8493812 commit 52d7a61e8d58a547a943f8f705764dc1898c621d
@@ -26,8 +26,9 @@

<Metadata>

<Event name="ThreadStart" category="Java Application" label="Java Thread Start" thread="true" startTime="false">
<Field type="Thread" name="thread" label="Java Thread" />
<Event name="ThreadStart" category="Java Application" label="Java Thread Start" thread="true" startTime="false" stackTrace="true">
<Field type="Thread" name="thread" label="New Java Thread" />
<Field type="Thread" name="parentThread" label="Parent Java Thread" />
</Event>

<Event name="ThreadEnd" category="Java Application" label="Java Thread End" thread="true" startTime="false">
@@ -56,7 +56,11 @@ JfrThreadLocal::JfrThreadLocal() :
_stackdepth(0),
_entering_suspend_flag(0),
_excluded(false),
_dead(false) {}
_dead(false) {

Thread* thread = Thread::current_or_null();
_parent_trace_id = thread != NULL ? thread->jfr_thread_local()->trace_id() : (traceid)0;
}

u8 JfrThreadLocal::add_data_lost(u8 value) {
_data_lost += value;
@@ -79,6 +83,7 @@ const JfrBlobHandle& JfrThreadLocal::thread_blob() const {
static void send_java_thread_start_event(JavaThread* jt) {
EventThreadStart event;
event.set_thread(jt->jfr_thread_local()->thread_id());
event.set_parentThread(jt->jfr_thread_local()->parent_thread_id());
event.commit();
}

@@ -94,6 +99,9 @@ void JfrThreadLocal::on_start(Thread* t) {
}
}
}
if (t->jfr_thread_local()->has_cached_stack_trace()) {
t->jfr_thread_local()->clear_cached_stack_trace();
}
}

static void send_java_thread_end_events(traceid id, JavaThread* jt) {
@@ -52,6 +52,7 @@ class JfrThreadLocal {
volatile jint _entering_suspend_flag;
bool _excluded;
bool _dead;
traceid _parent_trace_id;

JfrBuffer* install_native_buffer() const;
JfrBuffer* install_java_buffer() const;
@@ -128,6 +129,10 @@ class JfrThreadLocal {
_trace_id = thread_id;
}

traceid parent_thread_id() const {
return _parent_trace_id;
}

void set_cached_stack_trace_id(traceid id, unsigned int hash = 0) {
_stack_trace_id = id;
_stack_trace_hash = hash;
@@ -3659,7 +3659,14 @@ static void post_thread_start_event(const JavaThread* jt) {
EventThreadStart event;
if (event.should_commit()) {
event.set_thread(JFR_THREAD_ID(jt));
event.commit();
event.set_parentThread((traceid)0);
if (EventThreadStart::is_stacktrace_enabled()) {
jt->jfr_thread_local()->set_cached_stack_trace_id((traceid)0);
event.commit();
jt->jfr_thread_local()->clear_cached_stack_trace();
} else {
event.commit();
}
}
}

@@ -94,6 +94,7 @@
#endif

#include <errno.h>
#include <jfr/recorder/jfrRecorder.hpp>

/*
NOTE about use of any ctor or function call that can trigger a safepoint/GC:
@@ -2882,6 +2883,15 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
os::native_thread_creation_failed_msg());
}

#if INCLUDE_JFR
if (JfrRecorder::is_recording() && EventThreadStart::is_enabled() &&
EventThreadStart::is_stacktrace_enabled()) {
JfrThreadLocal* tl = native_thread->jfr_thread_local();
// skip Thread.start() and Thread.start0()
tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(thread, 2));
}
#endif

Thread::start(native_thread);

JVM_END
@@ -54,6 +54,7 @@

<event name="jdk.ThreadStart">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ThreadEnd">
@@ -54,6 +54,7 @@

<event name="jdk.ThreadStart">
<setting name="enabled">true</setting>
<setting name="stackTrace">true</setting>
</event>

<event name="jdk.ThreadEnd">
@@ -25,12 +25,17 @@

package jdk.jfr.event.runtime;

import static jdk.test.lib.Asserts.assertEQ;
import static jdk.test.lib.Asserts.assertNotNull;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordedMethod;
import jdk.jfr.consumer.RecordedStackTrace;
import jdk.test.lib.jfr.EventNames;
import jdk.test.lib.jfr.Events;

@@ -62,19 +67,27 @@ public static void main(String[] args) throws Throwable {
recording.stop();

int currThreadIndex = 0;
long currentThreadId = Thread.currentThread().getId();
List<RecordedEvent> events = Events.fromRecording(recording);
events.sort((e1, e2) -> e1.getStartTime().compareTo(e2.getStartTime()));
Events.hasEvents(events);
for (RecordedEvent event : events) {
System.out.println("Event:" + event);
if (event.getThread().getJavaThreadId() != currentThreadId) {
if (!event.getThread().getJavaName().startsWith(THREAD_NAME_PREFIX)) {
continue;
}
System.out.println("Event:" + event);
// Threads should be started and stopped in the correct order.
Events.assertEventThread(event, threads[currThreadIndex % threads.length]);
String eventName = currThreadIndex < threads.length ? EVENT_NAME_THREAD_START : EVENT_NAME_THREAD_END;
if (!eventName.equals(event.getEventType().getName())) {
throw new Exception("Expected event of tyoe " + eventName + " but got " + event.getEventType().getName());
throw new Exception("Expected event of type " + eventName + " but got " + event.getEventType().getName());
}

if (eventName == EVENT_NAME_THREAD_START) {
Events.assertEventThread(event, "parentThread", Thread.currentThread());
RecordedStackTrace stackTrace = event.getValue("stackTrace");
assertNotNull(stackTrace);
RecordedMethod topMethod = stackTrace.getFrames().get(0).getMethod();
assertEQ(topMethod.getName(), "startThread");
}
currThreadIndex++;
}

0 comments on commit 52d7a61

Please sign in to comment.