See regressionTestsInWaiting/SleepFrameCountTest.java Name: tb29552 Date: 11/22/2002 FULL PRODUCT VERSION : java version "1.4.1_01" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01) Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode) FULL OPERATING SYSTEM VERSION : Microsoft Windows XP [Version 5.1.2600] ADDITIONAL OPERATING SYSTEMS : Linux (Redhat 7.2) A DESCRIPTION OF THE PROBLEM : Starting with JDK 1.4.1, my debugger can no longer interrogate the call stack of a thread blocked in a call to Thread.sleep(). It receives IncompatibleThreadStateExceptions, even when the thread is suspended. It receives this exception when calling ThreadReference.frameCount() or ThreadReference.frames(). Two programs are attached to demonstrate the problem. The first is a simple program that just issues a sleep(). The second uses the JDI API to attach to the test program and type the number of frames in the call stack of the "main" thread. When this program attaches to the test program, the failure is demonstrated. The program works fine if the test program is blocked in a call to wait() instead of Thread.sleep(). REGRESSION. Last worked in version 1.4 STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Run the first program (Sleeper) with the following options: java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n Sleeper 2. Run the second program (JDIStackBug) with tools.jar in the class path, on the same machine as the test program. 3. Observe IncompatibleThreadState exception, even though thread is suspended. EXPECTED VERSUS ACTUAL BEHAVIOR : Expect program that uses JDI to output the depth of the call stack. Instead, it encounters and exception. ERROR MESSAGES/STACK TRACES THAT OCCUR : com.sun.jdi.IncompatibleThreadStateException at com.sun.tools.jdi.ThreadReferenceImpl.frameCount(ThreadReferenceImpl.java:263) at JDIStackBug.test(JDIStackBug.java:70) at JDIStackBug.main(JDIStackBug.java:12) REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- Sleeper.java: class Sleeper { public static void main(String[] args) { new Sleeper().test(); } void test() { try { Thread.sleep(500000); } catch (InterruptedException e) {} } } JDIStackBug.java: import java.util.*; import java.io.*; import com.sun.jdi.*; import com.sun.jdi.connect.*; import com.sun.jdi.request.*; import com.sun.jdi.event.*; public class JDIStackBug { VirtualMachine vm; public static void main(String[] args) { new JDIStackBug().test(args); } void test(String[] args) { VirtualMachineManager vmManager = Bootstrap.virtualMachineManager(); List connectors = vmManager.attachingConnectors(); Iterator iterator = connectors.iterator(); AttachingConnector connector = null; while (iterator.hasNext()) { AttachingConnector candidate = (AttachingConnector) iterator.next(); if (candidate.name().equals("com.sun.jdi.SocketAttach")) connector = candidate; } if (connector == null) { System.err.println("Can't find connector \"com.sun.jdi.SocketAttach\""); return; } // Set startup options Map connectorArgs = connector.defaultArguments(); Connector.Argument argInfo = (Connector.Argument) connectorArgs.get("hostname"); argInfo.setValue("localhost"); argInfo = (Connector.Argument) connectorArgs.get("port"); argInfo.setValue("8000"); try { vm = connector.attach(connectorArgs); } catch (IllegalConnectorArgumentsException e) { System.err.println("Exception attaching to JVM:"); e.printStackTrace(); } catch (IOException e) { System.err.println("I/O Exception attaching to JVM:"); e.printStackTrace(); } System.out.println("Virtual machine attached."); Thread eventThread = new Thread(new Runnable() { public void run() { readEvents(); } }, "Event reading thread"); eventThread.start(); try { System.out.println("Suspending VM..."); vm.suspend(); List allThreads = vm.allThreads(); iterator = allThreads.iterator(); while (iterator.hasNext()) { ThreadReference thread = (ThreadReference) iterator.next(); if (thread.name().equals("main")) { vm.setDebugTraceMode(VirtualMachine.TRACE_ALL); System.out.println("Thread \"main\""); System.out.println(" suspended == "+thread.isSuspended()); // The following ThreadReference.frameCount() call fails System.out.println(" stack frame count == "+thread.frameCount()); vm.setDebugTraceMode(VirtualMachine.TRACE_NONE); } } } catch (Exception e) { e.printStackTrace(); } System.out.println("Resuming JVM..."); vm.resume(); System.out.println("Detaching from VM..."); vm.dispose(); } void readEvents() { EventQueue eventQueue = vm.eventQueue(); boolean connected = true; while (connected) { try { EventSet eventSet = eventQueue.remove(); EventIterator iterator = eventSet.eventIterator(); while (iterator.hasNext()) { Event event = iterator.nextEvent(); if (event instanceof VMDisconnectEvent) connected = false; } eventSet.resume(); } catch (InterruptedException e) { System.err.println("Thread reading JVM event queue was interrupted!"); } catch (VMDisconnectedException e) { System.out.println("Received a VMDisconnectedException"); connected = false; } } } } ---------- END SOURCE ---------- CUSTOMER WORKAROUND : I haven't found a workaround. (Review ID: 167072) ======================================================================
|