8231032: ThreadMXBean locking tests fail after JSR 166 refresh
Reviewed-by: martin, mchung, dholmes
This commit is contained in:
parent
3e3d90d6a1
commit
a9254cbcfa
src/java.base/share/classes/java/util/concurrent/locks
test/jdk
@ -130,7 +130,7 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||
}
|
||||
|
||||
public final boolean block() {
|
||||
while (!isReleasable()) LockSupport.park(this);
|
||||
while (!isReleasable()) LockSupport.park();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ public abstract class AbstractQueuedSynchronizer
|
||||
}
|
||||
|
||||
public final boolean block() {
|
||||
while (!isReleasable()) LockSupport.park(this);
|
||||
while (!isReleasable()) LockSupport.park();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -564,8 +564,6 @@ java/lang/management/ThreadMXBean/AllThreadIds.java 8131745 generic-
|
||||
javax/management/monitor/DerivedGaugeMonitorTest.java 8042211 generic-all
|
||||
javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java 8042215 generic-all
|
||||
|
||||
java/lang/management/ThreadMXBean/LockedSynchronizers.java 8231032 generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_io
|
||||
|
@ -76,6 +76,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.LockInfo;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
import java.lang.reflect.Constructor;
|
||||
@ -270,6 +271,9 @@ public class JSR166TestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadMXBean THREAD_MXBEAN
|
||||
= ManagementFactory.getThreadMXBean();
|
||||
|
||||
/**
|
||||
* The scaling factor to apply to standard delays used in tests.
|
||||
* May be initialized from any of:
|
||||
@ -1157,9 +1161,8 @@ public class JSR166TestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
|
||||
System.err.println("------ stacktrace dump start ------");
|
||||
for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true))
|
||||
for (ThreadInfo info : THREAD_MXBEAN.dumpAllThreads(true, true))
|
||||
if (threadOfInterest(info))
|
||||
System.err.print(info);
|
||||
System.err.println("------ stacktrace dump end ------");
|
||||
@ -1187,6 +1190,17 @@ public class JSR166TestCase extends TestCase {
|
||||
fail("timed out waiting for thread to enter thread state " + expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread's blocker's class name, if any, else null.
|
||||
*/
|
||||
String blockerClassName(Thread thread) {
|
||||
ThreadInfo threadInfo; LockInfo lockInfo;
|
||||
if ((threadInfo = THREAD_MXBEAN.getThreadInfo(thread.getId(), 0)) != null
|
||||
&& (lockInfo = threadInfo.getLockInfo()) != null)
|
||||
return lockInfo.getClassName();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that future.get times out, with the default timeout of
|
||||
* {@code timeoutMillis()}.
|
||||
@ -1485,6 +1499,14 @@ public class JSR166TestCase extends TestCase {
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new started daemon Thread running the given action,
|
||||
* wrapped in a CheckedRunnable.
|
||||
*/
|
||||
Thread newStartedThread(Action action) {
|
||||
return newStartedThread(checkedRunnable(action));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the specified time (in milliseconds) for the thread
|
||||
* to terminate (using {@link Thread#join(long)}), else interrupts
|
||||
@ -1532,6 +1554,13 @@ public class JSR166TestCase extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
Runnable checkedRunnable(Action action) {
|
||||
return new CheckedRunnable() {
|
||||
public void realRun() throws Throwable {
|
||||
action.run();
|
||||
}};
|
||||
}
|
||||
|
||||
public abstract class ThreadShouldThrow extends Thread {
|
||||
protected abstract void realRun() throws Throwable;
|
||||
|
||||
|
@ -39,10 +39,13 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import junit.framework.Test;
|
||||
@ -1222,4 +1225,65 @@ public class ReentrantLockTest extends JSR166TestCase {
|
||||
assertFalse(thread.isAlive());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ThreadMXBean reports the blockers that we expect.
|
||||
*/
|
||||
public void testBlockers() {
|
||||
if (!testImplementationDetails) return;
|
||||
final boolean fair = randomBoolean();
|
||||
final boolean timedAcquire = randomBoolean();
|
||||
final boolean timedAwait = randomBoolean();
|
||||
final String syncClassName = fair
|
||||
? "ReentrantLock$FairSync"
|
||||
: "ReentrantLock$NonfairSync";
|
||||
final String conditionClassName
|
||||
= "AbstractQueuedSynchronizer$ConditionObject";
|
||||
final Thread.State expectedAcquireState = timedAcquire
|
||||
? Thread.State.TIMED_WAITING
|
||||
: Thread.State.WAITING;
|
||||
final Thread.State expectedAwaitState = timedAwait
|
||||
? Thread.State.TIMED_WAITING
|
||||
: Thread.State.WAITING;
|
||||
final Lock lock = new ReentrantLock(fair);
|
||||
final Condition condition = lock.newCondition();
|
||||
final AtomicBoolean conditionSatisfied = new AtomicBoolean(false);
|
||||
lock.lock();
|
||||
final Thread thread = newStartedThread((Action) () -> {
|
||||
if (timedAcquire)
|
||||
lock.tryLock(LONGER_DELAY_MS, MILLISECONDS);
|
||||
else
|
||||
lock.lock();
|
||||
while (!conditionSatisfied.get())
|
||||
if (timedAwait)
|
||||
condition.await(LONGER_DELAY_MS, MILLISECONDS);
|
||||
else
|
||||
condition.await();
|
||||
});
|
||||
Callable<Boolean> waitingForLock = () -> {
|
||||
String className;
|
||||
return thread.getState() == expectedAcquireState
|
||||
&& (className = blockerClassName(thread)) != null
|
||||
&& className.endsWith(syncClassName);
|
||||
};
|
||||
waitForThreadToEnterWaitState(thread, waitingForLock);
|
||||
|
||||
lock.unlock();
|
||||
Callable<Boolean> waitingForCondition = () -> {
|
||||
String className;
|
||||
return thread.getState() == expectedAwaitState
|
||||
&& (className = blockerClassName(thread)) != null
|
||||
&& className.endsWith(conditionClassName);
|
||||
};
|
||||
waitForThreadToEnterWaitState(thread, waitingForCondition);
|
||||
|
||||
// politely release the waiter
|
||||
conditionSatisfied.set(true);
|
||||
lock.lock();
|
||||
try {
|
||||
condition.signal();
|
||||
} finally { lock.unlock(); }
|
||||
|
||||
awaitTermination(thread);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
@ -1707,4 +1708,64 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
|
||||
assertTrue(lock.writeLock().toString().contains("Unlocked"));
|
||||
}
|
||||
|
||||
/**
|
||||
* ThreadMXBean reports the blockers that we expect.
|
||||
*/
|
||||
public void testBlockers() {
|
||||
if (!testImplementationDetails) return;
|
||||
final boolean fair = randomBoolean();
|
||||
final boolean timedAcquire = randomBoolean();
|
||||
final boolean timedAwait = randomBoolean();
|
||||
final String syncClassName = fair
|
||||
? "ReentrantReadWriteLock$FairSync"
|
||||
: "ReentrantReadWriteLock$NonfairSync";
|
||||
final String conditionClassName
|
||||
= "AbstractQueuedSynchronizer$ConditionObject";
|
||||
final Thread.State expectedAcquireState = timedAcquire
|
||||
? Thread.State.TIMED_WAITING
|
||||
: Thread.State.WAITING;
|
||||
final Thread.State expectedAwaitState = timedAwait
|
||||
? Thread.State.TIMED_WAITING
|
||||
: Thread.State.WAITING;
|
||||
final Lock lock = new ReentrantReadWriteLock(fair).writeLock();
|
||||
final Condition condition = lock.newCondition();
|
||||
final AtomicBoolean conditionSatisfied = new AtomicBoolean(false);
|
||||
lock.lock();
|
||||
final Thread thread = newStartedThread((Action) () -> {
|
||||
if (timedAcquire)
|
||||
lock.tryLock(LONGER_DELAY_MS, MILLISECONDS);
|
||||
else
|
||||
lock.lock();
|
||||
while (!conditionSatisfied.get())
|
||||
if (timedAwait)
|
||||
condition.await(LONGER_DELAY_MS, MILLISECONDS);
|
||||
else
|
||||
condition.await();
|
||||
});
|
||||
Callable<Boolean> waitingForLock = () -> {
|
||||
String className;
|
||||
return thread.getState() == expectedAcquireState
|
||||
&& (className = blockerClassName(thread)) != null
|
||||
&& className.endsWith(syncClassName);
|
||||
};
|
||||
waitForThreadToEnterWaitState(thread, waitingForLock);
|
||||
|
||||
lock.unlock();
|
||||
Callable<Boolean> waitingForCondition = () -> {
|
||||
String className;
|
||||
return thread.getState() == expectedAwaitState
|
||||
&& (className = blockerClassName(thread)) != null
|
||||
&& className.endsWith(conditionClassName);
|
||||
};
|
||||
waitForThreadToEnterWaitState(thread, waitingForCondition);
|
||||
|
||||
// politely release the waiter
|
||||
conditionSatisfied.set(true);
|
||||
lock.lock();
|
||||
try {
|
||||
condition.signal();
|
||||
} finally { lock.unlock(); }
|
||||
|
||||
awaitTermination(thread);
|
||||
}
|
||||
}
|
||||
|
@ -12,4 +12,6 @@ grant {
|
||||
permission java.lang.RuntimePermission "accessDeclaredMembers";
|
||||
permission java.io.FilePermission "<<ALL FILES>>", "read";
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
// Allows test methods to inspect test thread state
|
||||
permission java.lang.management.ManagementPermission "monitor";
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user