Skip to content

Commit a9254cb

Browse files
author
Doug Lea
committed
8231032: ThreadMXBean locking tests fail after JSR 166 refresh
Reviewed-by: martin, mchung, dholmes
1 parent 3e3d90d commit a9254cb

File tree

7 files changed

+160
-6
lines changed

7 files changed

+160
-6
lines changed

src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public final boolean isReleasable() {
130130
}
131131

132132
public final boolean block() {
133-
while (!isReleasable()) LockSupport.park(this);
133+
while (!isReleasable()) LockSupport.park();
134134
return true;
135135
}
136136
}

src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ public final boolean isReleasable() {
502502
}
503503

504504
public final boolean block() {
505-
while (!isReleasable()) LockSupport.park(this);
505+
while (!isReleasable()) LockSupport.park();
506506
return true;
507507
}
508508
}

test/jdk/ProblemList.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,6 @@ java/lang/management/ThreadMXBean/AllThreadIds.java 8131745 generic-
564564
javax/management/monitor/DerivedGaugeMonitorTest.java 8042211 generic-all
565565
javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java 8042215 generic-all
566566

567-
java/lang/management/ThreadMXBean/LockedSynchronizers.java 8231032 generic-all
568-
569567
############################################################################
570568

571569
# jdk_io

test/jdk/java/util/concurrent/tck/JSR166TestCase.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import java.io.ObjectInputStream;
7777
import java.io.ObjectOutputStream;
7878
import java.lang.management.ManagementFactory;
79+
import java.lang.management.LockInfo;
7980
import java.lang.management.ThreadInfo;
8081
import java.lang.management.ThreadMXBean;
8182
import java.lang.reflect.Constructor;
@@ -270,6 +271,9 @@ private static float systemPropertyValue(String name) {
270271
}
271272
}
272273

274+
private static final ThreadMXBean THREAD_MXBEAN
275+
= ManagementFactory.getThreadMXBean();
276+
273277
/**
274278
* The scaling factor to apply to standard delays used in tests.
275279
* May be initialized from any of:
@@ -1157,9 +1161,8 @@ static void dumpTestThreads() {
11571161
}
11581162
}
11591163

1160-
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
11611164
System.err.println("------ stacktrace dump start ------");
1162-
for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true))
1165+
for (ThreadInfo info : THREAD_MXBEAN.dumpAllThreads(true, true))
11631166
if (threadOfInterest(info))
11641167
System.err.print(info);
11651168
System.err.println("------ stacktrace dump end ------");
@@ -1187,6 +1190,17 @@ else if (s == Thread.State.TERMINATED)
11871190
fail("timed out waiting for thread to enter thread state " + expected);
11881191
}
11891192

1193+
/**
1194+
* Returns the thread's blocker's class name, if any, else null.
1195+
*/
1196+
String blockerClassName(Thread thread) {
1197+
ThreadInfo threadInfo; LockInfo lockInfo;
1198+
if ((threadInfo = THREAD_MXBEAN.getThreadInfo(thread.getId(), 0)) != null
1199+
&& (lockInfo = threadInfo.getLockInfo()) != null)
1200+
return lockInfo.getClassName();
1201+
return null;
1202+
}
1203+
11901204
/**
11911205
* Checks that future.get times out, with the default timeout of
11921206
* {@code timeoutMillis()}.
@@ -1485,6 +1499,14 @@ Thread newStartedThread(Runnable runnable) {
14851499
return t;
14861500
}
14871501

1502+
/**
1503+
* Returns a new started daemon Thread running the given action,
1504+
* wrapped in a CheckedRunnable.
1505+
*/
1506+
Thread newStartedThread(Action action) {
1507+
return newStartedThread(checkedRunnable(action));
1508+
}
1509+
14881510
/**
14891511
* Waits for the specified time (in milliseconds) for the thread
14901512
* to terminate (using {@link Thread#join(long)}), else interrupts
@@ -1532,6 +1554,13 @@ public final void run() {
15321554
}
15331555
}
15341556

1557+
Runnable checkedRunnable(Action action) {
1558+
return new CheckedRunnable() {
1559+
public void realRun() throws Throwable {
1560+
action.run();
1561+
}};
1562+
}
1563+
15351564
public abstract class ThreadShouldThrow extends Thread {
15361565
protected abstract void realRun() throws Throwable;
15371566

test/jdk/java/util/concurrent/tck/ReentrantLockTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,13 @@
3939
import java.util.Arrays;
4040
import java.util.Collection;
4141
import java.util.HashSet;
42+
import java.util.concurrent.Callable;
4243
import java.util.concurrent.CountDownLatch;
4344
import java.util.concurrent.CyclicBarrier;
4445
import java.util.concurrent.ThreadLocalRandom;
46+
import java.util.concurrent.atomic.AtomicBoolean;
4547
import java.util.concurrent.locks.Condition;
48+
import java.util.concurrent.locks.Lock;
4649
import java.util.concurrent.locks.ReentrantLock;
4750

4851
import junit.framework.Test;
@@ -1222,4 +1225,65 @@ public void testBug8187408() throws InterruptedException {
12221225
assertFalse(thread.isAlive());
12231226
}
12241227
}
1228+
1229+
/**
1230+
* ThreadMXBean reports the blockers that we expect.
1231+
*/
1232+
public void testBlockers() {
1233+
if (!testImplementationDetails) return;
1234+
final boolean fair = randomBoolean();
1235+
final boolean timedAcquire = randomBoolean();
1236+
final boolean timedAwait = randomBoolean();
1237+
final String syncClassName = fair
1238+
? "ReentrantLock$FairSync"
1239+
: "ReentrantLock$NonfairSync";
1240+
final String conditionClassName
1241+
= "AbstractQueuedSynchronizer$ConditionObject";
1242+
final Thread.State expectedAcquireState = timedAcquire
1243+
? Thread.State.TIMED_WAITING
1244+
: Thread.State.WAITING;
1245+
final Thread.State expectedAwaitState = timedAwait
1246+
? Thread.State.TIMED_WAITING
1247+
: Thread.State.WAITING;
1248+
final Lock lock = new ReentrantLock(fair);
1249+
final Condition condition = lock.newCondition();
1250+
final AtomicBoolean conditionSatisfied = new AtomicBoolean(false);
1251+
lock.lock();
1252+
final Thread thread = newStartedThread((Action) () -> {
1253+
if (timedAcquire)
1254+
lock.tryLock(LONGER_DELAY_MS, MILLISECONDS);
1255+
else
1256+
lock.lock();
1257+
while (!conditionSatisfied.get())
1258+
if (timedAwait)
1259+
condition.await(LONGER_DELAY_MS, MILLISECONDS);
1260+
else
1261+
condition.await();
1262+
});
1263+
Callable<Boolean> waitingForLock = () -> {
1264+
String className;
1265+
return thread.getState() == expectedAcquireState
1266+
&& (className = blockerClassName(thread)) != null
1267+
&& className.endsWith(syncClassName);
1268+
};
1269+
waitForThreadToEnterWaitState(thread, waitingForLock);
1270+
1271+
lock.unlock();
1272+
Callable<Boolean> waitingForCondition = () -> {
1273+
String className;
1274+
return thread.getState() == expectedAwaitState
1275+
&& (className = blockerClassName(thread)) != null
1276+
&& className.endsWith(conditionClassName);
1277+
};
1278+
waitForThreadToEnterWaitState(thread, waitingForCondition);
1279+
1280+
// politely release the waiter
1281+
conditionSatisfied.set(true);
1282+
lock.lock();
1283+
try {
1284+
condition.signal();
1285+
} finally { lock.unlock(); }
1286+
1287+
awaitTermination(thread);
1288+
}
12251289
}

test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.Arrays;
3939
import java.util.Collection;
4040
import java.util.HashSet;
41+
import java.util.concurrent.Callable;
4142
import java.util.concurrent.CountDownLatch;
4243
import java.util.concurrent.atomic.AtomicBoolean;
4344
import java.util.concurrent.locks.Condition;
@@ -1707,4 +1708,64 @@ public void testWriteLockToString(boolean fair) {
17071708
assertTrue(lock.writeLock().toString().contains("Unlocked"));
17081709
}
17091710

1711+
/**
1712+
* ThreadMXBean reports the blockers that we expect.
1713+
*/
1714+
public void testBlockers() {
1715+
if (!testImplementationDetails) return;
1716+
final boolean fair = randomBoolean();
1717+
final boolean timedAcquire = randomBoolean();
1718+
final boolean timedAwait = randomBoolean();
1719+
final String syncClassName = fair
1720+
? "ReentrantReadWriteLock$FairSync"
1721+
: "ReentrantReadWriteLock$NonfairSync";
1722+
final String conditionClassName
1723+
= "AbstractQueuedSynchronizer$ConditionObject";
1724+
final Thread.State expectedAcquireState = timedAcquire
1725+
? Thread.State.TIMED_WAITING
1726+
: Thread.State.WAITING;
1727+
final Thread.State expectedAwaitState = timedAwait
1728+
? Thread.State.TIMED_WAITING
1729+
: Thread.State.WAITING;
1730+
final Lock lock = new ReentrantReadWriteLock(fair).writeLock();
1731+
final Condition condition = lock.newCondition();
1732+
final AtomicBoolean conditionSatisfied = new AtomicBoolean(false);
1733+
lock.lock();
1734+
final Thread thread = newStartedThread((Action) () -> {
1735+
if (timedAcquire)
1736+
lock.tryLock(LONGER_DELAY_MS, MILLISECONDS);
1737+
else
1738+
lock.lock();
1739+
while (!conditionSatisfied.get())
1740+
if (timedAwait)
1741+
condition.await(LONGER_DELAY_MS, MILLISECONDS);
1742+
else
1743+
condition.await();
1744+
});
1745+
Callable<Boolean> waitingForLock = () -> {
1746+
String className;
1747+
return thread.getState() == expectedAcquireState
1748+
&& (className = blockerClassName(thread)) != null
1749+
&& className.endsWith(syncClassName);
1750+
};
1751+
waitForThreadToEnterWaitState(thread, waitingForLock);
1752+
1753+
lock.unlock();
1754+
Callable<Boolean> waitingForCondition = () -> {
1755+
String className;
1756+
return thread.getState() == expectedAwaitState
1757+
&& (className = blockerClassName(thread)) != null
1758+
&& className.endsWith(conditionClassName);
1759+
};
1760+
waitForThreadToEnterWaitState(thread, waitingForCondition);
1761+
1762+
// politely release the waiter
1763+
conditionSatisfied.set(true);
1764+
lock.lock();
1765+
try {
1766+
condition.signal();
1767+
} finally { lock.unlock(); }
1768+
1769+
awaitTermination(thread);
1770+
}
17101771
}

test/jdk/java/util/concurrent/tck/tck.policy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ grant {
1212
permission java.lang.RuntimePermission "accessDeclaredMembers";
1313
permission java.io.FilePermission "<<ALL FILES>>", "read";
1414
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
15+
// Allows test methods to inspect test thread state
16+
permission java.lang.management.ManagementPermission "monitor";
1517
};

0 commit comments

Comments
 (0)