OpenJDK / jdk / jdk10
changeset 21614:c7336876755e
8022208: Intermittent test failures in java/lang/Thread/ThreadStateTest.java
6944188: ThreadMXBean/ThreadStateTest.java fails intermittently
Reviewed-by: dholmes, chegar
author | mchung |
---|---|
date | Tue, 05 Nov 2013 17:33:26 -0800 |
parents | 19a42489efef |
children | 0231a565a5b7 |
files | jdk/test/java/lang/Thread/ThreadStateController.java jdk/test/java/lang/Thread/ThreadStateTest.java jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java |
diffstat | 4 files changed, 597 insertions(+), 701 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/Thread/ThreadStateController.java Tue Nov 05 17:33:26 2013 -0800 @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.LockSupport; + +/** + * ThreadStateController allows a thread to request this thread to transition + * to a specific thread state. The {@linkplain #transitionTo request} is + * a blocking call that the calling thread will wait until this thread is about + * going to the new state. Only one request of state transition at a time + * is supported (the Phaser expects only parties of 2 to arrive and advance + * to next phase). + */ +public class ThreadStateController extends Thread { + // used to achieve waiting states + private final Object lock; + public ThreadStateController(String name, Object lock) { + super(name); + this.lock = lock; + } + + public void checkThreadState(Thread.State expected) { + // maximum number of retries when checking for thread state. + final int MAX_RETRY = 500; + + // wait for the thread to transition to the expected state. + // There is a small window between the thread checking the state + // and the thread actual entering that state. + Thread.State state; + int retryCount=0; + while ((state = getState()) != expected && retryCount < MAX_RETRY) { + pause(10); + retryCount++; + } + + if (state == null) { + throw new RuntimeException(getName() + " expected to have " + + expected + " but got null."); + } + + if (state != expected) { + throw new RuntimeException(String.format("%s expected in %s state but got %s " + + "(iterations %d interrupted %d)%n", + getName(), expected, state, iterations.get(), interrupted.get())); + } + } + + public static void pause(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // Phaser to sync between the main thread putting + // this thread into various states + private final Phaser phaser = new Phaser(2); + private volatile int newState = S_RUNNABLE; + private volatile int state = 0; + private boolean done = false; + + private static final int S_RUNNABLE = 1; + private static final int S_BLOCKED = 2; + private static final int S_WAITING = 3; + private static final int S_TIMED_WAITING = 4; + private static final int S_PARKED = 5; + private static final int S_TIMED_PARKED = 6; + private static final int S_SLEEPING = 7; + private static final int S_TERMINATE = 8; + + // for debugging + private AtomicInteger iterations = new AtomicInteger(); + private AtomicInteger interrupted = new AtomicInteger(); + public void run() { + // this thread has started + while (!done) { + // state transition + int nextState = state; + if (newState != state) { + nextState = newState; + iterations.set(0); + interrupted.set(0); + } + iterations.incrementAndGet(); + switch (nextState) { + case S_RUNNABLE: { + stateChange(nextState); + double sum = 0; + for (int i = 0; i < 1000; i++) { + double r = Math.random(); + double x = Math.pow(3, r); + sum += x - r; + } + break; + } + case S_BLOCKED: { + System.out.format("%d: %s is going to block (interations %d)%n", + getId(), getName(), iterations.get()); + stateChange(nextState); + // going to block on lock + synchronized (lock) { + System.out.format("%d: %s acquired the lock (interations %d)%n", + getId(), getName(), iterations.get()); + try { + // this thread has escaped the BLOCKED state + // release the lock and a short wait before continue + lock.wait(10); + } catch (InterruptedException e) { + // ignore + interrupted.incrementAndGet(); + } + } + break; + } + case S_WAITING: { + synchronized (lock) { + System.out.format("%d: %s is going to waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + try { + stateChange(nextState); + lock.wait(); + System.out.format("%d: %s wakes up from waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + } catch (InterruptedException e) { + // ignore + interrupted.incrementAndGet(); + } + } + break; + } + case S_TIMED_WAITING: { + synchronized (lock) { + System.out.format("%d: %s is going to timed waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + try { + stateChange(nextState); + lock.wait(10000); + System.out.format("%d: %s wakes up from timed waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + } catch (InterruptedException e) { + // ignore + interrupted.incrementAndGet(); + } + } + break; + } + case S_PARKED: { + System.out.format("%d: %s is going to park (interations %d)%n", + getId(), getName(), iterations.get()); + stateChange(nextState); + LockSupport.park(); + break; + } + case S_TIMED_PARKED: { + System.out.format("%d: %s is going to timed park (interations %d)%n", + getId(), getName(), iterations.get()); + long deadline = System.currentTimeMillis() + 10000*1000; + stateChange(nextState); + LockSupport.parkUntil(deadline); + break; + } + case S_SLEEPING: { + System.out.format("%d: %s is going to sleep (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + try { + stateChange(nextState); + Thread.sleep(1000000); + } catch (InterruptedException e) { + // finish sleeping + interrupted.incrementAndGet(); + } + break; + } + case S_TERMINATE: { + done = true; + stateChange(nextState); + break; + } + default: + break; + } + } + } + + /** + * Change the state if it matches newState. + */ + private void stateChange(int nextState) { + // no state change + if (state == nextState) + return; + + // transition to the new state + if (newState == nextState) { + state = nextState; + phaser.arrive(); + System.out.format("%d: state change: %s %s%n", + getId(), toStateName(nextState), phaserToString(phaser)); + return; + } + + // should never reach here + throw new RuntimeException("current " + state + " next " + nextState + + " new state " + newState); + } + + /** + * Blocks until this thread transitions to the given state + */ + public void transitionTo(Thread.State tstate) throws InterruptedException { + switch (tstate) { + case RUNNABLE: + nextState(S_RUNNABLE); + break; + case BLOCKED: + nextState(S_BLOCKED); + break; + case WAITING: + nextState(S_WAITING); + break; + case TIMED_WAITING: + nextState(S_TIMED_WAITING); + break; + case TERMINATED: + nextState(S_TERMINATE); + break; + default: + break; + } + } + + /** + * Blocks until this thread transitions to sleeping + */ + public void transitionToSleep() throws InterruptedException { + nextState(S_SLEEPING); + } + + /** + * Blocks until this thread transitions to park or timed park + */ + public void transitionToPark(boolean timed) throws InterruptedException { + nextState(timed ? S_TIMED_PARKED : S_PARKED); + } + + private void nextState(int s) throws InterruptedException { + final long id = Thread.currentThread().getId(); + System.out.format("%d: wait until the thread transitions to %s %s%n", + id, toStateName(s), phaserToString(phaser)); + this.newState = s; + int phase = phaser.arrive(); + System.out.format("%d: awaiting party arrive %s %s%n", + id, toStateName(s), phaserToString(phaser)); + for (;;) { + // when this thread has changed its state before it waits or parks + // on a lock, a potential race might happen if it misses the notify + // or unpark. Hence await for the phaser to advance with timeout + // to cope with this race condition. + switch (state) { + case S_WAITING: + case S_TIMED_WAITING: + synchronized (lock) { + lock.notify(); + } + break; + case S_PARKED: + case S_TIMED_PARKED: + LockSupport.unpark(this); + break; + case S_SLEEPING: + this.interrupt(); + break; + case S_BLOCKED: + default: + break; + } + try { + phaser.awaitAdvanceInterruptibly(phase, 100, TimeUnit.MILLISECONDS); + System.out.format("%d: arrived at %s %s%n", + id, toStateName(s), phaserToString(phaser)); + return; + } catch (TimeoutException ex) { + // this thread hasn't arrived at this phase + System.out.format("%d: Timeout: %s%n", id, phaser); + } + } + } + private String phaserToString(Phaser p) { + return "[phase = " + p.getPhase() + + " parties = " + p.getRegisteredParties() + + " arrived = " + p.getArrivedParties() + "]"; + } + private String toStateName(int state) { + switch (state) { + case S_RUNNABLE: + return "runnable"; + case S_WAITING: + return "waiting"; + case S_TIMED_WAITING: + return "timed waiting"; + case S_PARKED: + return "parked"; + case S_TIMED_PARKED: + return "timed parked"; + case S_SLEEPING: + return "sleeping"; + case S_BLOCKED: + return "blocked"; + case S_TERMINATE: + return "terminated"; + default: + return "unknown " + state; + } + } +}
--- a/jdk/test/java/lang/Thread/ThreadStateTest.java Tue Nov 05 11:18:20 2013 -0800 +++ b/jdk/test/java/lang/Thread/ThreadStateTest.java Tue Nov 05 17:33:26 2013 -0800 @@ -21,77 +21,64 @@ * questions. */ +import static java.lang.Thread.State.*; + /* * @test - * @bug 5014783 + * @bug 5014783 8022208 * @summary Basic unit test of thread states returned by * Thread.getState(). * * @author Mandy Chung - * - * @build ThreadStateTest + * @build ThreadStateTest ThreadStateController * @run main ThreadStateTest */ -import java.util.concurrent.locks.LockSupport; -import java.util.concurrent.Phaser; - public class ThreadStateTest { - // maximum number of retries when checking for thread state. - static final int MAX_RETRY = 500; - private static boolean testFailed = false; // used to achieve waiting states - static final Object globalLock = new Object(); + private static final Object globalLock = new Object(); - public static void main(String[] argv) { + public static void main(String[] argv) throws Exception { // Call Thread.getState to force all initialization done // before test verification begins. Thread.currentThread().getState(); - MyThread myThread = new MyThread("MyThread"); + ThreadStateController thread = new ThreadStateController("StateChanger", globalLock); + thread.setDaemon(true); // before myThread starts - checkThreadState(myThread, Thread.State.NEW); + thread.checkThreadState(NEW); - myThread.start(); - myThread.waitUntilStarted(); - checkThreadState(myThread, Thread.State.RUNNABLE); + thread.start(); + thread.transitionTo(RUNNABLE); + thread.checkThreadState(RUNNABLE); synchronized (globalLock) { - myThread.goBlocked(); - checkThreadState(myThread, Thread.State.BLOCKED); + thread.transitionTo(BLOCKED); + thread.checkThreadState(BLOCKED); } - myThread.goWaiting(); - checkThreadState(myThread, Thread.State.WAITING); - - myThread.goTimedWaiting(); - checkThreadState(myThread, Thread.State.TIMED_WAITING); + thread.transitionTo(WAITING); + thread.checkThreadState(WAITING); + thread.transitionTo(TIMED_WAITING); + thread.checkThreadState(TIMED_WAITING); - /* - *********** park and parkUntil seems not working - * ignore this case for now. - * Bug ID 5062095 - *********************************************** + thread.transitionToPark(true /* timed park*/); + thread.checkThreadState(TIMED_WAITING); - myThread.goParked(); - checkThreadState(myThread, Thread.State.WAITING); - - myThread.goTimedParked(); - checkThreadState(myThread, Thread.State.TIMED_WAITING); - */ + thread.transitionToPark(false /* indefinite park */); + thread.checkThreadState(WAITING); + thread.transitionToSleep(); + thread.checkThreadState(TIMED_WAITING); - myThread.goSleeping(); - checkThreadState(myThread, Thread.State.TIMED_WAITING); - - myThread.terminate(); - checkThreadState(myThread, Thread.State.TERMINATED); + thread.transitionTo(TERMINATED); + thread.checkThreadState(TERMINATED); try { - myThread.join(); + thread.join(); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("Unexpected exception."); @@ -102,241 +89,4 @@ throw new RuntimeException("TEST FAILED."); System.out.println("Test passed."); } - - private static void checkThreadState(Thread t, Thread.State expected) { - // wait for the thread to transition to the expected state. - // There is a small window between the thread checking the state - // and the thread actual entering that state. - Thread.State state; - int retryCount=0; - while ((state = t.getState()) != expected && retryCount < MAX_RETRY) { - if (state != Thread.State.RUNNABLE) { - throw new RuntimeException("Thread not in expected state yet," + - " but it should at least be RUNNABLE"); - } - goSleep(10); - retryCount++; - } - - System.out.println("Checking thread state " + state); - if (state == null) { - throw new RuntimeException(t.getName() + " expected to have " + - expected + " but got null."); - } - - if (state != expected) { - throw new RuntimeException(t.getName() + " expected to have " + - expected + " but got " + state); - } - } - - private static void goSleep(long ms) { - try { - Thread.sleep(ms); - } catch (InterruptedException e) { - e.printStackTrace(); - System.out.println("Unexpected exception."); - testFailed = true; - } - } - - static class MyThread extends Thread { - // Phaser to sync between the main thread putting - // this thread into various states - private Phaser phaser = new Phaser(2); - - MyThread(String name) { - super(name); - } - - private final int RUNNABLE = 0; - private final int BLOCKED = 1; - private final int WAITING = 2; - private final int TIMED_WAITING = 3; - private final int PARKED = 4; - private final int TIMED_PARKED = 5; - private final int SLEEPING = 6; - private final int TERMINATE = 7; - - private volatile int state = RUNNABLE; - - private boolean done = false; - public void run() { - // Signal main thread to continue. - phaser.arriveAndAwaitAdvance(); - - while (!done) { - switch (state) { - case RUNNABLE: { - double sum = 0; - for (int i = 0; i < 1000; i++) { - double r = Math.random(); - double x = Math.pow(3, r); - sum += x - r; - } - break; - } - case BLOCKED: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to block."); - synchronized (globalLock) { - // finish blocking - state = RUNNABLE; - } - break; - } - case WAITING: { - synchronized (globalLock) { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to wait."); - try { - globalLock.wait(); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case TIMED_WAITING: { - synchronized (globalLock) { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to timed wait."); - try { - globalLock.wait(10000); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case PARKED: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to park."); - LockSupport.park(); - // give a chance for the main thread to block - goSleep(10); - break; - } - case TIMED_PARKED: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to timed park."); - long deadline = System.currentTimeMillis() + 10000*1000; - LockSupport.parkUntil(deadline); - - // give a chance for the main thread to block - goSleep(10); - break; - } - case SLEEPING: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to sleep."); - try { - Thread.sleep(1000000); - } catch (InterruptedException e) { - // finish sleeping - } - break; - } - case TERMINATE: { - done = true; - // signal main thread. - phaser.arrive(); - break; - } - default: - break; - } - } - } - - public void waitUntilStarted() { - // wait for MyThread. - phaser.arriveAndAwaitAdvance(); - } - - public void goBlocked() { - System.out.println("Waiting myThread to go blocked."); - setState(BLOCKED); - // wait for MyThread to get to a point just before being blocked - phaser.arriveAndAwaitAdvance(); - } - - public void goWaiting() { - System.out.println("Waiting myThread to go waiting."); - setState(WAITING); - // wait for MyThread to get to just before wait on object. - phaser.arriveAndAwaitAdvance(); - } - - public void goTimedWaiting() { - System.out.println("Waiting myThread to go timed waiting."); - setState(TIMED_WAITING); - // wait for MyThread to get to just before timed wait call. - phaser.arriveAndAwaitAdvance(); - } - - public void goParked() { - System.out.println("Waiting myThread to go parked."); - setState(PARKED); - // wait for MyThread to get to just before parked. - phaser.arriveAndAwaitAdvance(); - } - - public void goTimedParked() { - System.out.println("Waiting myThread to go timed parked."); - setState(TIMED_PARKED); - // wait for MyThread to get to just before timed park. - phaser.arriveAndAwaitAdvance(); - } - - public void goSleeping() { - System.out.println("Waiting myThread to go sleeping."); - setState(SLEEPING); - // wait for MyThread to get to just before sleeping - phaser.arriveAndAwaitAdvance(); - } - - public void terminate() { - System.out.println("Waiting myThread to terminate."); - setState(TERMINATE); - // wait for MyThread to get to just before terminate - phaser.arriveAndAwaitAdvance(); - } - - private void setState(int newState) { - switch (state) { - case BLOCKED: - while (state == BLOCKED) { - goSleep(10); - } - state = newState; - break; - case WAITING: - case TIMED_WAITING: - state = newState; - synchronized (globalLock) { - globalLock.notify(); - } - break; - case PARKED: - case TIMED_PARKED: - state = newState; - LockSupport.unpark(this); - break; - case SLEEPING: - state = newState; - this.interrupt(); - break; - default: - state = newState; - break; - } - } - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java Tue Nov 05 17:33:26 2013 -0800 @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4967283 5080203 8022208 + * @summary Basic unit test of thread states returned by + * ThreadMXBean.getThreadInfo.getThreadState(). + * It also tests lock information returned by ThreadInfo. + * + * @author Mandy Chung + * + * @library ../../Thread + * @build ThreadMXBeanStateTest ThreadStateController + * @run main ThreadMXBeanStateTest + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; +import java.lang.management.ThreadInfo; +import static java.lang.Thread.State.*; + +public class ThreadMXBeanStateTest { + private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean(); + + static class Lock { + private String name; + Lock(String name) { + this.name = name; + } + public String toString() { + return name; + } + } + private static Lock globalLock = new Lock("my lock"); + + public static void main(String[] argv) throws Exception { + // Force thread state initialization now before the test + // verification begins. + Thread.currentThread().getState(); + ThreadStateController thread = new ThreadStateController("StateChanger", globalLock); + thread.setDaemon(true); + + // before myThread starts + thread.checkThreadState(NEW); + + thread.start(); + thread.transitionTo(RUNNABLE); + thread.checkThreadState(RUNNABLE); + checkLockInfo(thread, RUNNABLE, null, null); + + thread.suspend(); + ThreadStateController.pause(10); + thread.checkThreadState(RUNNABLE); + checkSuspendedThreadState(thread, RUNNABLE); + thread.resume(); + + synchronized (globalLock) { + thread.transitionTo(BLOCKED); + thread.checkThreadState(BLOCKED); + checkLockInfo(thread, BLOCKED, + globalLock, Thread.currentThread()); + } + + thread.transitionTo(WAITING); + thread.checkThreadState(WAITING); + checkLockInfo(thread, Thread.State.WAITING, + globalLock, null); + + thread.transitionTo(TIMED_WAITING); + thread.checkThreadState(TIMED_WAITING); + checkLockInfo(thread, TIMED_WAITING, + globalLock, null); + + + thread.transitionToPark(true /* timed park */); + thread.checkThreadState(TIMED_WAITING); + checkLockInfo(thread, TIMED_WAITING, null, null); + + thread.transitionToPark(false /* indefinite park */); + thread.checkThreadState(WAITING); + checkLockInfo(thread, WAITING, null, null); + + thread.transitionToSleep(); + thread.checkThreadState(TIMED_WAITING); + checkLockInfo(thread, TIMED_WAITING, null, null); + + thread.transitionTo(TERMINATED); + thread.checkThreadState(TERMINATED); + + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println("TEST FAILED: Unexpected exception."); + throw new RuntimeException(e); + } + System.out.println("Test passed."); + } + + private static void checkSuspendedThreadState(ThreadStateController t, Thread.State state) { + ThreadInfo info = getThreadInfo(t, state); + if (info == null) { + throw new RuntimeException(t.getName() + + " expected to have ThreadInfo " + + " but got null."); + } + + if (info.getThreadState() != state) { + throw new RuntimeException(t.getName() + " expected to be in " + + state + " state but got " + info.getThreadState()); + } + + if (!info.isSuspended()) { + throw new RuntimeException(t.getName() + " expected to be suspended " + + " but isSuspended() returns " + info.isSuspended()); + } + } + + private static String getLockName(Object lock) { + if (lock == null) return null; + + return lock.getClass().getName() + '@' + + Integer.toHexString(System.identityHashCode(lock)); + } + + // maximum number of retries when checking for thread state. + private static final int MAX_RETRY = 500; + private static ThreadInfo getThreadInfo(ThreadStateController t, Thread.State expected) { + // wait for the thread to transition to the expected state. + // There is a small window between the thread checking the state + // and the thread actual entering that state. + int retryCount=0; + ThreadInfo info = tm.getThreadInfo(t.getId()); + while (info.getThreadState() != expected && retryCount < MAX_RETRY) { + ThreadStateController.pause(10); + retryCount++; + info = tm.getThreadInfo(t.getId()); + } + return info; + } + + private static void checkLockInfo(ThreadStateController t, Thread.State state, + Object lock, Thread owner) { + ThreadInfo info = getThreadInfo(t, state); + if (info == null) { + throw new RuntimeException(t.getName() + + " expected to have ThreadInfo " + + " but got null."); + } + + if (info.getThreadState() != state) { + throw new RuntimeException(t.getName() + " expected to be in " + + state + " state but got " + info.getThreadState()); + } + + if (lock == null && info.getLockName() != null) { + throw new RuntimeException(t.getName() + + " expected not to be blocked on any lock" + + " but got " + info.getLockName()); + } + String expectedLockName = getLockName(lock); + if (lock != null && info.getLockName() == null) { + throw new RuntimeException(t.getName() + + " expected to be blocked on lock [" + expectedLockName + + "] but got null."); + } + + if (lock != null && !expectedLockName.equals(info.getLockName())) { + throw new RuntimeException(t.getName() + + " expected to be blocked on lock [" + expectedLockName + + "] but got [" + info.getLockName() + "]."); + } + + if (owner == null && info.getLockOwnerName() != null) { + throw new RuntimeException("Lock owner is expected " + + " to be null but got " + info.getLockOwnerName()); + } + + if (owner != null && info.getLockOwnerName() == null) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + + " but got null."); + } + if (owner != null && !info.getLockOwnerName().equals(owner.getName())) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + + " but got " + owner.getName()); + } + if (owner == null && info.getLockOwnerId() != -1) { + throw new RuntimeException("Lock owner is expected " + + " to be -1 but got " + info.getLockOwnerId()); + } + + if (owner != null && info.getLockOwnerId() <= 0) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + "(id = " + owner.getId() + + ") but got " + info.getLockOwnerId()); + } + if (owner != null && info.getLockOwnerId() != owner.getId()) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + "(id = " + owner.getId() + + ") but got " + info.getLockOwnerId()); + } + if (info.isSuspended()) { + throw new RuntimeException(t.getName() + + " isSuspended() returns " + info.isSuspended()); + } + } +}
--- a/jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java Tue Nov 05 11:18:20 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4967283 5080203 - * @summary Basic unit test of thread states returned by - * ThreadMXBean.getThreadInfo.getThreadState(). - * It also tests lock information returned by ThreadInfo. - * - * @author Mandy Chung - * - * @build ThreadExecutionSynchronizer Utils - * @run main ThreadStateTest - */ - -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadMXBean; -import java.lang.management.ThreadInfo; - -import java.util.concurrent.locks.LockSupport; - -public class ThreadStateTest { - private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean(); - - static class Lock { - private String name; - Lock(String name) { - this.name = name; - } - public String toString() { - return name; - } - } - private static Lock globalLock = new Lock("my lock"); - - public static void main(String[] argv) { - // Force thread state initialization now before the test - // verification begins. - Thread.currentThread().getState(); - - MyThread myThread = new MyThread("MyThread"); - - // before myThread starts - // Utils.checkThreadState(myThread, Thread.State.NEW); - - myThread.start(); - myThread.waitUntilStarted(); - Utils.checkThreadState(myThread, Thread.State.RUNNABLE); - checkLockInfo(myThread, Thread.State.RUNNABLE, null, null); - - myThread.suspend(); - Utils.goSleep(10); - checkSuspendedThreadState(myThread, Thread.State.RUNNABLE); - myThread.resume(); - - synchronized (globalLock) { - myThread.goBlocked(); - Utils.checkThreadState(myThread, Thread.State.BLOCKED); - checkLockInfo(myThread, Thread.State.BLOCKED, - globalLock, Thread.currentThread()); - } - - myThread.goWaiting(); - Utils.checkThreadState(myThread, Thread.State.WAITING); - checkLockInfo(myThread, Thread.State.WAITING, - globalLock, null); - - myThread.goTimedWaiting(); - Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING); - checkLockInfo(myThread, Thread.State.TIMED_WAITING, - globalLock, null); - - - - /* - *********** parkUntil seems not working - * ignore this park case for now. - - Bug ID : 5062095 - *********************************************** - myThread.goParked(); - Utils.checkThreadState(myThread, Thread.State.WAITING); - checkLockInfo(myThread, Thread.State.WAITING, null, null); - - myThread.goTimedParked(); - Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING); - checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null); - - */ - - myThread.goSleeping(); - Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING); - checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null); - - - myThread.terminate(); - // Utils.checkThreadState(myThread, ThreadState.TERMINATED); - - try { - myThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - System.out.println("TEST FAILED: Unexpected exception."); - throw new RuntimeException(e); - } - System.out.println("Test passed."); - } - - private static void checkSuspendedThreadState(Thread t, Thread.State state) { - ThreadInfo info = tm.getThreadInfo(t.getId()); - if (info == null) { - throw new RuntimeException(t.getName() + - " expected to have ThreadInfo " + - " but got null."); - } - - if (info.getThreadState() != state) { - throw new RuntimeException(t.getName() + " expected to be in " + - state + " state but got " + info.getThreadState()); - } - - if (!info.isSuspended()) { - throw new RuntimeException(t.getName() + " expected to be suspended " + - " but isSuspended() returns " + info.isSuspended()); - } - Utils.checkThreadState(t, state); - } - - private static String getLockName(Object lock) { - if (lock == null) return null; - - return lock.getClass().getName() + '@' + - Integer.toHexString(System.identityHashCode(lock)); - } - - private static void checkLockInfo(Thread t, Thread.State state, Object lock, Thread owner) { - ThreadInfo info = tm.getThreadInfo(t.getId()); - if (info == null) { - throw new RuntimeException(t.getName() + - " expected to have ThreadInfo " + - " but got null."); - } - - if (info.getThreadState() != state) { - throw new RuntimeException(t.getName() + " expected to be in " + - state + " state but got " + info.getThreadState()); - } - - if (lock == null && info.getLockName() != null) { - throw new RuntimeException(t.getName() + - " expected not to be blocked on any lock" + - " but got " + info.getLockName()); - } - String expectedLockName = getLockName(lock); - if (lock != null && info.getLockName() == null) { - throw new RuntimeException(t.getName() + - " expected to be blocked on lock [" + expectedLockName + - "] but got null."); - } - - if (lock != null && !expectedLockName.equals(info.getLockName())) { - throw new RuntimeException(t.getName() + - " expected to be blocked on lock [" + expectedLockName + - "] but got [" + info.getLockName() + "]."); - } - - if (owner == null && info.getLockOwnerName() != null) { - throw new RuntimeException("Lock owner is expected " + - " to be null but got " + info.getLockOwnerName()); - } - - if (owner != null && info.getLockOwnerName() == null) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + - " but got null."); - } - if (owner != null && !info.getLockOwnerName().equals(owner.getName())) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + - " but got " + owner.getName()); - } - if (owner == null && info.getLockOwnerId() != -1) { - throw new RuntimeException("Lock owner is expected " + - " to be -1 but got " + info.getLockOwnerId()); - } - - if (owner != null && info.getLockOwnerId() <= 0) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + "(id = " + owner.getId() + - ") but got " + info.getLockOwnerId()); - } - if (owner != null && info.getLockOwnerId() != owner.getId()) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + "(id = " + owner.getId() + - ") but got " + info.getLockOwnerId()); - } - if (info.isSuspended()) { - throw new RuntimeException(t.getName() + - " isSuspended() returns " + info.isSuspended()); - } - } - - static class MyThread extends Thread { - private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer(); - - MyThread(String name) { - super(name); - } - - private final int RUNNABLE = 0; - private final int BLOCKED = 1; - private final int WAITING = 2; - private final int TIMED_WAITING = 3; - private final int PARKED = 4; - private final int TIMED_PARKED = 5; - private final int SLEEPING = 6; - private final int TERMINATE = 7; - private int state = RUNNABLE; - - private boolean done = false; - public void run() { - // Signal main thread to continue. - thrsync.signal(); - while (!done) { - switch (state) { - case RUNNABLE: { - double sum = 0; - for (int i = 0; i < 1000; i++) { - double r = Math.random(); - double x = Math.pow(3, r); - sum += x - r; - } - break; - } - case BLOCKED: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to block."); - synchronized (globalLock) { - // finish blocking - state = RUNNABLE; - } - break; - } - case WAITING: { - synchronized (globalLock) { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to wait."); - try { - globalLock.wait(); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case TIMED_WAITING: { - synchronized (globalLock) { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to timed wait."); - try { - globalLock.wait(10000); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case PARKED: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to park."); - LockSupport.park(); - // give a chance for the main thread to block - System.out.println(" myThread is going to park."); - Utils.goSleep(10); - break; - } - case TIMED_PARKED: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to timed park."); - long deadline = System.currentTimeMillis() + 10000*1000; - LockSupport.parkUntil(deadline); - - // give a chance for the main thread to block - Utils.goSleep(10); - break; - } - case SLEEPING: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to sleep."); - try { - Thread.sleep(1000000); - } catch (InterruptedException e) { - // finish sleeping - interrupted(); - } - break; - } - case TERMINATE: { - done = true; - // signal main thread. - thrsync.signal(); - break; - } - default: - break; - } - } - } - public void waitUntilStarted() { - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(10); - } - - public void goBlocked() { - System.out.println("Waiting myThread to go blocked."); - setState(BLOCKED); - // wait for MyThread to get blocked - thrsync.waitForSignal(); - Utils.goSleep(20); - } - - public void goWaiting() { - System.out.println("Waiting myThread to go waiting."); - setState(WAITING); - // wait for MyThread to wait on object. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void goTimedWaiting() { - System.out.println("Waiting myThread to go timed waiting."); - setState(TIMED_WAITING); - // wait for MyThread timed wait call. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void goParked() { - System.out.println("Waiting myThread to go parked."); - setState(PARKED); - // wait for MyThread state change to PARKED. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void goTimedParked() { - System.out.println("Waiting myThread to go timed parked."); - setState(TIMED_PARKED); - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - - public void goSleeping() { - System.out.println("Waiting myThread to go sleeping."); - setState(SLEEPING); - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void terminate() { - System.out.println("Waiting myThread to terminate."); - setState(TERMINATE); - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - - private void setState(int newState) { - switch (state) { - case BLOCKED: - while (state == BLOCKED) { - Utils.goSleep(20); - } - state = newState; - break; - case WAITING: - case TIMED_WAITING: - state = newState; - synchronized (globalLock) { - globalLock.notify(); - } - break; - case PARKED: - case TIMED_PARKED: - state = newState; - LockSupport.unpark(this); - break; - case SLEEPING: - state = newState; - this.interrupt(); - break; - default: - state = newState; - break; - } - } - } -}