JDK-5104215 : Blocked thread status is incorrectly reported as runnable
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: generic
  • Submitted: 2004-09-20
  • Updated: 2005-07-27
  • Resolved: 2005-07-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u6Fixed 6 b45Fixed
Description
/* This test is used to test jdb reporting wrong thread status information
   Steps to reproduce the problem:
     jdb FooTest
     stop at FooTest:53 - the last line in changeVarOne()
     run
     cont    -  a few times
     threads

   All but one of Thread-0 through Thread-9 should be "waiting on a
   monitor". But jdb reports more more than one threads "running". If you do a
   where <thread id> on the running threads, you will see they are actually
   waiting to enter the synchornized method. It seemed like once a thread has 
   been marked as running, jdb will always think it's a running thread even.
*/
public class FooTest
{
    private static int _var;

    public static void main(String[] args) throws Exception
    {
        for( int i = 0; i < 10; i++ )
        {
            final int j = i;
            try
            {
                new Thread(
                    new Runnable()
                    {
                        public void run()
                        {
                            method( j );
                            method( j );
                            method( j );
                        }

                        public void method( int i )
                        {
                            changeVarOne(i);
                        }

                    }
                ).start();
            }
            catch( Exception e ) {}
        }
    }

    public static int _varOne = -1;

    synchronized static public void changeVarOne(int value)
    {
        boolean b = false;
        _varOne = value;
    }
}

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
22-09-2004

EVALUATION A thread entering a contended monitor can observe that the monitor owner is NULL. This can happen when another thread is exiting the monitor. When this arises the thread's "threadStatus" isn't set to MONITOR_ENTER even though the thread may block if another thread obtains the monitor. The implication of the bug is that Thread.getState() or JVMTI's GetThreadState may return the thread state as RUNNABLE even though the thread is blocked trying to enter a synchronized block/method. The MonitorContentedEnter event is not impacted this issue. ###@###.### 2004-09-20 ###@###.### 2005-07-20 19:05:41 GMT
20-09-2004

SUGGESTED FIX Attached webrev.tar contains the final change. We need to replace obj_m->owner() != NULL check with obj_m->contentions() > 0 instead of the following suggested fix. ###@###.### 2005-07-20 ------- threadService.hpp ------- *** /tmp/sccs.DHai0s Mon Sep 20 09:30:00 2004 --- threadService.hpp Sat Sep 18 16:05:49 2004 *************** *** 372,378 **** // enter done for external java world objects and it is contended. All other cases // like for vm internal objects and for external objects which are not contended // thread status is not changed and contended enter stat is not collected. ! if (is_alive() && ServiceUtil::visible_oop((oop)obj_m->object()) && obj_m->owner() !=NULL) { set_thread_status(java_lang_Thread::BLOCKED_ON_MONITOR_ENTER); _stat = java_thread->get_thread_stat(); _stat->contended_enter(); --- 372,378 ---- // enter done for external java world objects and it is contended. All other cases // like for vm internal objects and for external objects which are not contended // thread status is not changed and contended enter stat is not collected. ! if (is_alive() && ServiceUtil::visible_oop((oop)obj_m->object())) { set_thread_status(java_lang_Thread::BLOCKED_ON_MONITOR_ENTER); _stat = java_thread->get_thread_stat(); _stat->contended_enter(); ###@###.### 2004-09-20 ###@###.### 2005-07-20 19:05:41 GMT
20-09-2004