7

By Java source code we have that

// variable not written or updated anywhere on this class
private volatile int threadStatus = 0;

public State getState() {
    // get current thread state
    return sun.misc.VM.toThreadState(threadStatus);
}

How and where is threadStatus updated?

The idea would be to eventually try to weave around updating methods with AOP and have a callback on threadStatus changes.

Hulk
  • 6,399
  • 1
  • 30
  • 52
Frankie
  • 24,627
  • 10
  • 79
  • 121

2 Answers2

6

In OpenJDK source code in file hotspot/src/share/vm/classfile/javaClasses.cpp you can see following code:

// Write the thread status value to threadStatus field in java.lang.Thread java class.
void java_lang_Thread::set_thread_status(oop java_thread,
                                         java_lang_Thread::ThreadStatus status) {
  // The threadStatus is only present starting in 1.5
  if (_thread_status_offset > 0) {
    java_thread->int_field_put(_thread_status_offset, status);
  }
}

It looks like state is managed in native code. It means that you can't intercept its change from java code.

talex
  • 17,973
  • 3
  • 29
  • 66
  • Really helpful. Thanks. If you have an alternative ideia on how I may monitor Thread status besides constantly pinging Thread.getStatus() please let me know. – Frankie Nov 21 '18 at 18:30
  • If you want to monitor BLOCK status there is nothing else you can do. How you will use this information? Maybe there is other way to achieve your goal. – talex Nov 22 '18 at 03:08
  • @Frankie for debugging purposes, you *could* theoretically try to build your own OpenJDK vm with a modified `java_lang_Thread::set_thread_status` that calls some callback in addition to updating the thread status – Hulk Nov 22 '18 at 09:51
  • @Hulk that looks like one way to do it. – Frankie Nov 23 '18 at 04:44
  • @talex I'm pushing Java a bit to the limits of what would be logical but trying to experiment with creating a fast-forward time-line. So instead of running real-time the program would run as fast as possible mocking time but, without it being dependent on changes to the user's code. I've done pretty well so far with AspectJ but there are corner cases where threads are interdependent on each other where it would help to have a callback stating changes. – Frankie Nov 23 '18 at 04:48
1

This is an internal thread status that should reflect Thread State as NEW, RUNNABLE,..

I found a Netbeans issue that suggest that toThreadState() is/can be implemented outside JDK code:

bugfix #262633, toThreadState() implemented locally, do not rely on JDK

So possibly also modifying threadStatus not updated in Java code, Notice 0 value stand for NEW thread status:

/** taken from sun.misc.VM
 * 
 * Returns Thread.State for the given threadStatus
 */
private static Thread.State toThreadState(int threadStatus) {
    if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) {
        return State.RUNNABLE;
    } else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) {
        return State.BLOCKED;
    } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) {
        return State.WAITING;
    } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) {
        return State.TIMED_WAITING;
    } else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) {
        return State.TERMINATED;
    } else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) {
        return State.NEW;
    } else {
        return State.RUNNABLE;
    }
}
Ori Marko
  • 56,308
  • 23
  • 131
  • 233