Ensure GetThreadState works with Thread subtypes
We were incorrectly assuming that Thread has no subclasses. This is
not accurate.
Bug: 66704836
Test: ./test.py --host -j50
Change-Id: I4abd85b6c4e6add6d62854adb4f8912777292315
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index d437e52..da1c1bc 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -484,13 +484,18 @@
}
art::ScopedObjectAccess soa(self);
+ art::StackHandleScope<1> hs(self);
// Need to read the Java "started" field to know whether this is starting or terminated.
- art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
- art::ObjPtr<art::mirror::Class> klass = peer->GetClass();
- art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z");
+ art::Handle<art::mirror::Object> peer(hs.NewHandle(soa.Decode<art::mirror::Object>(thread)));
+ art::ObjPtr<art::mirror::Class> thread_klass =
+ soa.Decode<art::mirror::Class>(art::WellKnownClasses::java_lang_Thread);
+ if (!thread_klass->IsAssignableFrom(peer->GetClass())) {
+ return ERR(INVALID_THREAD);
+ }
+ art::ArtField* started_field = thread_klass->FindDeclaredInstanceField("started", "Z");
CHECK(started_field != nullptr);
- bool started = started_field->GetBoolean(peer) != 0;
+ bool started = started_field->GetBoolean(peer.Get()) != 0;
constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
diff --git a/test/924-threads/expected.txt b/test/924-threads/expected.txt
index 1eb2e1b..e529559 100644
--- a/test/924-threads/expected.txt
+++ b/test/924-threads/expected.txt
@@ -26,6 +26,15 @@
class dalvik.system.PathClassLoader
5
5
+Thread type is class java.lang.Thread
+0 = NEW
+191 = ALIVE|WAITING_INDEFINITELY|WAITING|IN_OBJECT_WAIT
+1a1 = ALIVE|WAITING_WITH_TIMEOUT|WAITING|IN_OBJECT_WAIT
+401 = ALIVE|BLOCKED_ON_MONITOR_ENTER
+e1 = ALIVE|WAITING_WITH_TIMEOUT|SLEEPING|WAITING
+5 = ALIVE|RUNNABLE
+2 = TERMINATED
+Thread type is class art.Test924$ExtThread
0 = NEW
191 = ALIVE|WAITING_INDEFINITELY|WAITING|IN_OBJECT_WAIT
1a1 = ALIVE|WAITING_WITH_TIMEOUT|WAITING|IN_OBJECT_WAIT
diff --git a/test/924-threads/src/art/Test924.java b/test/924-threads/src/art/Test924.java
index b73eb30..1ff2c3f 100644
--- a/test/924-threads/src/art/Test924.java
+++ b/test/924-threads/src/art/Test924.java
@@ -21,6 +21,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.CountDownLatch;
+import java.util.function.Function;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -76,7 +77,9 @@
};
printThreadInfo(t4);
- doStateTests();
+ doCurrentThreadStateTests();
+ doStateTests(Thread::new);
+ doStateTests(ExtThread::new);
doAllThreadsTests();
@@ -85,14 +88,20 @@
doTestEvents();
}
+ private static final class ExtThread extends Thread {
+ public ExtThread(Runnable r) { super(r); }
+ }
+
private static class Holder {
volatile boolean flag = false;
}
- private static void doStateTests() throws Exception {
+ private static void doCurrentThreadStateTests() throws Exception {
System.out.println(Integer.toHexString(getThreadState(null)));
System.out.println(Integer.toHexString(getThreadState(Thread.currentThread())));
+ }
+ private static void doStateTests(Function<Runnable, Thread> mkThread) throws Exception {
final CountDownLatch cdl1 = new CountDownLatch(1);
final CountDownLatch cdl2 = new CountDownLatch(1);
final CountDownLatch cdl3_1 = new CountDownLatch(1);
@@ -133,7 +142,8 @@
}
};
- Thread t = new Thread(r);
+ Thread t = mkThread.apply(r);
+ System.out.println("Thread type is " + t.getClass());
printThreadState(t);
t.start();