Merge "Send ThreadEnd after clearing ThreadGroup."
diff --git a/runtime/thread.cc b/runtime/thread.cc
index b66365a..524e73d 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2159,11 +2159,11 @@
ScopedObjectAccess soa(self);
// We may need to call user-supplied managed code, do this before final clean-up.
HandleUncaughtExceptions(soa);
+ RemoveFromThreadGroup(soa);
Runtime* runtime = Runtime::Current();
if (runtime != nullptr) {
runtime->GetRuntimeCallbacks()->ThreadDeath(self);
}
- RemoveFromThreadGroup(soa);
// this.nativePeer = 0;
if (Runtime::Current()->IsActiveTransaction()) {
diff --git a/test/1923-frame-pop/src/art/Trace.java b/test/1923-frame-pop/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1923-frame-pop/src/art/Trace.java
+++ b/test/1923-frame-pop/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1924-frame-pop-toggle/src/art/Trace.java b/test/1924-frame-pop-toggle/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1924-frame-pop-toggle/src/art/Trace.java
+++ b/test/1924-frame-pop-toggle/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1925-self-frame-pop/src/art/Trace.java b/test/1925-self-frame-pop/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1925-self-frame-pop/src/art/Trace.java
+++ b/test/1925-self-frame-pop/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1926-missed-frame-pop/src/art/Trace.java b/test/1926-missed-frame-pop/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/1926-missed-frame-pop/src/art/Trace.java
+++ b/test/1926-missed-frame-pop/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/1936-thread-end-events/check b/test/1936-thread-end-events/check
new file mode 100644
index 0000000..8a84388
--- /dev/null
+++ b/test/1936-thread-end-events/check
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The RI sends an extra event that art doesn't. Add it to the expected output.
+if [[ "$TEST_RUNTIME" == "jvm" ]]; then
+ patch -p0 expected.txt < jvm-expected.patch >/dev/null
+fi
+
+./default-check "$@"
diff --git a/test/1936-thread-end-events/expected.txt b/test/1936-thread-end-events/expected.txt
new file mode 100644
index 0000000..6b71c5e
--- /dev/null
+++ b/test/1936-thread-end-events/expected.txt
@@ -0,0 +1,42 @@
+Entered public static void art.Test1936.foo()
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered void java.lang.ThreadGroup.threadTerminated(java.lang.Thread)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered private void java.lang.ThreadGroup.remove(java.lang.Thread)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered public static native void java.lang.System.arraycopy(java.lang.Object,int,java.lang.Object,int,int)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered public static void art.Test1936.NotifyThreadEnd(java.lang.Thread)
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
+Entered public static void art.Test1936.foo()
+Thread: test-thread
+ | alive: true
+ | interrupted: false
+ | daemon: false
+ | group: java.lang.ThreadGroup[name=main,maxpri=10]
+
diff --git a/test/1936-thread-end-events/info.txt b/test/1936-thread-end-events/info.txt
new file mode 100644
index 0000000..51986c4
--- /dev/null
+++ b/test/1936-thread-end-events/info.txt
@@ -0,0 +1,6 @@
+Tests JVMTI ThreadEnd bug
+
+We had a bug where we were still sending events after JVMTI_EVENT_THREAD_END due
+to where we sent the event. This test ensures that the placement of the
+THREAD_END event is correct.
+
diff --git a/test/1936-thread-end-events/jvm-expected.patch b/test/1936-thread-end-events/jvm-expected.patch
new file mode 100644
index 0000000..ddb30a3
--- /dev/null
+++ b/test/1936-thread-end-events/jvm-expected.patch
@@ -0,0 +1,16 @@
+7a8,14
+> Entered private void java.lang.Thread.exit()
+> Thread: test-thread
+> | alive: true
+> | interrupted: false
+> | daemon: false
+> | group: java.lang.ThreadGroup[name=main,maxpri=10]
+>
+34c41
+< | group: java.lang.ThreadGroup[name=main,maxpri=10]
+---
+> | group: null
+41c48
+< | group: java.lang.ThreadGroup[name=main,maxpri=10]
+---
+> | group: null
diff --git a/test/1936-thread-end-events/method_trace.cc b/test/1936-thread-end-events/method_trace.cc
new file mode 100644
index 0000000..019b6a9
--- /dev/null
+++ b/test/1936-thread-end-events/method_trace.cc
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+
+#include <cstdio>
+#include <memory>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+
+#include "jni.h"
+#include "jvmti.h"
+#include "scoped_local_ref.h"
+
+// Test infrastructure
+#include "jni_binder.h"
+#include "jni_helper.h"
+#include "jvmti_helper.h"
+#include "test_env.h"
+#include "ti_macros.h"
+
+namespace art {
+namespace Test989StackTraceThrow {
+
+extern "C" JNIEXPORT
+jfloat JNICALL Java_art_Test989_returnFloatNative(JNIEnv* env, jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "doGetFloat", "()F");
+ return env->CallStaticFloatMethod(klass, targetMethod);
+}
+extern "C" JNIEXPORT
+jdouble JNICALL Java_art_Test989_returnDoubleNative(JNIEnv* env, jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "doGetDouble", "()D");
+ return env->CallStaticDoubleMethod(klass, targetMethod);
+}
+
+extern "C" JNIEXPORT jobject JNICALL Java_art_Test989_returnValueNative(JNIEnv* env, jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "mkTestObject", "()Ljava/lang/Object;");
+ return env->CallStaticObjectMethod(klass, targetMethod);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test989_doNothingNative(JNIEnv* env ATTRIBUTE_UNUSED,
+ jclass klass ATTRIBUTE_UNUSED) {
+ return;
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test989_throwANative(JNIEnv* env,
+ jclass klass) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "doThrowA", "()V");
+ env->CallStaticVoidMethod(klass, targetMethod);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Test989_acceptValueNative(JNIEnv* env,
+ jclass klass,
+ jobject arg) {
+ jmethodID targetMethod = env->GetStaticMethodID(klass, "printObject", "(Ljava/lang/Object;)V");
+ env->CallStaticVoidMethod(klass, targetMethod, arg);
+}
+
+} // namespace Test989StackTraceThrow
+} // namespace art
+
diff --git a/test/1936-thread-end-events/run b/test/1936-thread-end-events/run
new file mode 100755
index 0000000..51875a7
--- /dev/null
+++ b/test/1936-thread-end-events/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Ask for stack traces to be dumped to a file rather than to stdout.
+./default-run "$@" --jvmti
diff --git a/test/1936-thread-end-events/src/Main.java b/test/1936-thread-end-events/src/Main.java
new file mode 100644
index 0000000..da66fc3
--- /dev/null
+++ b/test/1936-thread-end-events/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ art.Test1936.run();
+ }
+}
diff --git a/test/1936-thread-end-events/src/art/Test1936.java b/test/1936-thread-end-events/src/art/Test1936.java
new file mode 100644
index 0000000..868deca
--- /dev/null
+++ b/test/1936-thread-end-events/src/art/Test1936.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+public class Test1936 {
+ public static void foo() {}
+
+ public static void NotifyThreadEnd(Thread me) {
+ // Don't actually do anything.
+ foo();
+ }
+
+ public static void NotifyMethodEntry(Object o) {
+ System.out.println("Entered " + o.toString());
+ Thread me = Thread.currentThread();
+ System.out.println(String.format(
+ "Thread: %s\n" +
+ " | alive: %b\n" +
+ " | interrupted: %b\n" +
+ " | daemon: %b\n" +
+ " | group: %s\n",
+ me.getName(), me.isAlive(), me.isInterrupted(), me.isDaemon(), me.getThreadGroup()));
+ }
+
+ public static native void waitForever();
+ private static void setupTracing(Thread target) throws Exception {
+ Trace.disableTracing(target);
+ Trace.enableTracing2(
+ Test1936.class,
+ Test1936.class.getDeclaredMethod("NotifyMethodEntry", Object.class),
+ /*exit*/null,
+ /*field_access*/null,
+ /*field_modify*/null,
+ /*single_step*/null,
+ /*thread_start*/null,
+ Test1936.class.getDeclaredMethod("NotifyThreadEnd", Thread.class),
+ target);
+ }
+
+
+ public static void run() throws Exception {
+ Thread t = new Thread(() -> {
+ try {
+ setupTracing(Thread.currentThread());
+ foo();
+ } catch (Exception e) {
+ System.out.println("Caught exception " + e + "!");
+ e.printStackTrace();
+ }
+ }, "test-thread");
+ t.start();
+ t.join();
+ }
+}
diff --git a/test/1936-thread-end-events/src/art/Trace.java b/test/1936-thread-end-events/src/art/Trace.java
new file mode 100644
index 0000000..8999bb1
--- /dev/null
+++ b/test/1936-thread-end-events/src/art/Trace.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package art;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class Trace {
+ public static native void enableTracing(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Thread thr);
+ public static native void disableTracing(Thread thr);
+
+ public static void enableFieldTracing(Class<?> methodClass,
+ Method fieldAccess,
+ Method fieldModify,
+ Thread thr) {
+ enableTracing(methodClass, null, null, fieldAccess, fieldModify, null, thr);
+ }
+
+ public static void enableMethodTracing(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Thread thr) {
+ enableTracing(methodClass, entryMethod, exitMethod, null, null, null, thr);
+ }
+
+ public static void enableSingleStepTracing(Class<?> methodClass,
+ Method singleStep,
+ Thread thr) {
+ enableTracing(methodClass, null, null, null, null, singleStep, thr);
+ }
+
+ public static native void watchFieldAccess(Field f);
+ public static native void watchFieldModification(Field f);
+ public static native void watchAllFieldAccesses();
+ public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
+}
diff --git a/test/988-method-trace/src/art/Trace.java b/test/988-method-trace/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/988-method-trace/src/art/Trace.java
+++ b/test/988-method-trace/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/989-method-trace-throw/src/art/Trace.java b/test/989-method-trace-throw/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/989-method-trace-throw/src/art/Trace.java
+++ b/test/989-method-trace-throw/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/990-field-trace/src/art/Trace.java b/test/990-field-trace/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/990-field-trace/src/art/Trace.java
+++ b/test/990-field-trace/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/991-field-trace-2/src/art/Trace.java b/test/991-field-trace-2/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/991-field-trace-2/src/art/Trace.java
+++ b/test/991-field-trace-2/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/997-single-step/src/art/Trace.java b/test/997-single-step/src/art/Trace.java
index ba3d397..8999bb1 100644
--- a/test/997-single-step/src/art/Trace.java
+++ b/test/997-single-step/src/art/Trace.java
@@ -53,4 +53,16 @@
public static native void watchFieldModification(Field f);
public static native void watchAllFieldAccesses();
public static native void watchAllFieldModifications();
+
+ // the names, arguments, and even line numbers of these functions are embedded in the tests so we
+ // need to add to the bottom and not modify old ones to maintain compat.
+ public static native void enableTracing2(Class<?> methodClass,
+ Method entryMethod,
+ Method exitMethod,
+ Method fieldAccess,
+ Method fieldModify,
+ Method singleStep,
+ Method ThreadStart,
+ Method ThreadEnd,
+ Thread thr);
}
diff --git a/test/ti-agent/trace_helper.cc b/test/ti-agent/trace_helper.cc
index 1f8ceff..8b74c7c 100644
--- a/test/ti-agent/trace_helper.cc
+++ b/test/ti-agent/trace_helper.cc
@@ -34,11 +34,36 @@
jmethodID field_access;
jmethodID field_modify;
jmethodID single_step;
+ jmethodID thread_start;
+ jmethodID thread_end;
bool in_callback;
bool access_watch_on_load;
bool modify_watch_on_load;
};
+static void threadStartCB(jvmtiEnv* jvmti,
+ JNIEnv* jnienv,
+ jthread thread) {
+ TraceData* data = nullptr;
+ if (JvmtiErrorToException(jnienv, jvmti,
+ jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
+ return;
+ }
+ CHECK(data->thread_start != nullptr);
+ jnienv->CallStaticVoidMethod(data->test_klass, data->thread_start, thread);
+}
+static void threadEndCB(jvmtiEnv* jvmti,
+ JNIEnv* jnienv,
+ jthread thread) {
+ TraceData* data = nullptr;
+ if (JvmtiErrorToException(jnienv, jvmti,
+ jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) {
+ return;
+ }
+ CHECK(data->thread_end != nullptr);
+ jnienv->CallStaticVoidMethod(data->test_klass, data->thread_end, thread);
+}
+
static void singleStepCB(jvmtiEnv* jvmti,
JNIEnv* jnienv,
jthread thread,
@@ -362,7 +387,7 @@
env->DeleteLocalRef(klass);
}
-extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing(
+extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing2(
JNIEnv* env,
jclass trace ATTRIBUTE_UNUSED,
jclass klass,
@@ -371,6 +396,8 @@
jobject field_access,
jobject field_modify,
jobject single_step,
+ jobject thread_start,
+ jobject thread_end,
jthread thr) {
TraceData* data = nullptr;
if (JvmtiErrorToException(env,
@@ -386,6 +413,8 @@
data->field_access = field_access != nullptr ? env->FromReflectedMethod(field_access) : nullptr;
data->field_modify = field_modify != nullptr ? env->FromReflectedMethod(field_modify) : nullptr;
data->single_step = single_step != nullptr ? env->FromReflectedMethod(single_step) : nullptr;
+ data->thread_start = thread_start != nullptr ? env->FromReflectedMethod(thread_start) : nullptr;
+ data->thread_end = thread_end != nullptr ? env->FromReflectedMethod(thread_end) : nullptr;
data->in_callback = false;
TraceData* old_data = nullptr;
@@ -410,6 +439,8 @@
cb.FieldModification = fieldModificationCB;
cb.ClassPrepare = classPrepareCB;
cb.SingleStep = singleStepCB;
+ cb.ThreadStart = threadStartCB;
+ cb.ThreadEnd = threadEndCB;
if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)))) {
return;
}
@@ -453,6 +484,46 @@
thr))) {
return;
}
+ if (thread_start != nullptr &&
+ JvmtiErrorToException(env,
+ jvmti_env,
+ jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+ JVMTI_EVENT_THREAD_START,
+ thr))) {
+ return;
+ }
+ if (thread_end != nullptr &&
+ JvmtiErrorToException(env,
+ jvmti_env,
+ jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+ JVMTI_EVENT_THREAD_END,
+ thr))) {
+ return;
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing(
+ JNIEnv* env,
+ jclass trace,
+ jclass klass,
+ jobject enter,
+ jobject exit,
+ jobject field_access,
+ jobject field_modify,
+ jobject single_step,
+ jthread thr) {
+ Java_art_Trace_enableTracing2(env,
+ trace,
+ klass,
+ enter,
+ exit,
+ field_access,
+ field_modify,
+ single_step,
+ /* thread_start */ nullptr,
+ /* thread_end */ nullptr,
+ thr);
+ return;
}
extern "C" JNIEXPORT void JNICALL Java_art_Trace_disableTracing(