< prev index next >
test/jdk/java/util/concurrent/locks/Lock/TimedAcquireLeak.java
Print this page
8229442: AQS and lock classes refresh
Reviewed-by: martin
*** 40,49 ****
--- 40,51 ----
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
+ import java.util.ArrayList;
+ import java.util.Collections;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
*** 70,82 ****
static String javaProgramPath(String programName) {
return new File(bin, programName).getPath();
}
! static final String java = javaProgramPath("java");
! static final String jmap = javaProgramPath("jmap");
! static final String jps = javaProgramPath("jps");
static String outputOf(Reader r) throws IOException {
final StringBuilder sb = new StringBuilder();
final char[] buf = new char[1024];
int n;
--- 72,84 ----
static String javaProgramPath(String programName) {
return new File(bin, programName).getPath();
}
! static final String javaPath = javaProgramPath("java");
! static final String jmapPath = javaProgramPath("jmap");
! static final String jpsPath = javaProgramPath("jps");
static String outputOf(Reader r) throws IOException {
final StringBuilder sb = new StringBuilder();
final char[] buf = new char[1024];
int n;
*** 157,167 ****
} catch (Throwable t) { throw new Error(t); }
}
static String match(String s, String regex, int group) {
Matcher matcher = Pattern.compile(regex).matcher(s);
! matcher.find();
return matcher.group(group);
}
/** It's all about sending a message! */
static void sendByte(OutputStream s) throws IOException {
--- 159,173 ----
} catch (Throwable t) { throw new Error(t); }
}
static String match(String s, String regex, int group) {
Matcher matcher = Pattern.compile(regex).matcher(s);
! if (! matcher.find()) {
! String msg = String.format(
! "match failed: s=%s regex=%s", s, regex);
! throw new AssertionError(msg);
! }
return matcher.group(group);
}
/** It's all about sending a message! */
static void sendByte(OutputStream s) throws IOException {
*** 169,234 ****
s.flush();
}
static int objectsInUse(final Process child,
final String childPid,
! final String className) {
! final String regex =
! "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E(?:$| )";
! final Callable<Integer> objectsInUse =
! new Callable<Integer>() { public Integer call() {
! Integer i = Integer.parseInt(
! match(commandOutputOf(jmap, "-histo:live", childPid),
regex, 1));
if (i > 100)
System.out.print(
! commandOutputOf(jmap,
"-dump:file=dump,format=b",
childPid));
return i;
! }};
try { return rendezvousParent(child, objectsInUse); }
catch (Throwable t) { unexpected(t); return -1; }
}
static void realMain(String[] args) throws Throwable {
// jmap doesn't work on Windows
if (System.getProperty("os.name").startsWith("Windows"))
return;
final String childClassName = Job.class.getName();
! final String classToCheckForLeaks = Job.classToCheckForLeaks();
! final String uniqueID =
! String.valueOf(ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE));
!
! final String[] jobCmd = {
! java, "-Xmx8m", "-XX:+UsePerfData",
! "-classpath", System.getProperty("test.class.path"),
! childClassName, uniqueID
! };
final Process p = new ProcessBuilder(jobCmd).start();
// Ensure subprocess jvm has started, so that jps can find it
p.getInputStream().read();
sendByte(p.getOutputStream());
final String childPid =
! match(commandOutputOf(jps, "-m"),
"(?m)^ *([0-9]+) +\\Q"+childClassName+"\\E *"+uniqueID+"$", 1);
! final int n0 = objectsInUse(p, childPid, classToCheckForLeaks);
! final int n1 = objectsInUse(p, childPid, classToCheckForLeaks);
equal(p.waitFor(), 0);
equal(p.exitValue(), 0);
failed += p.exitValue();
// Check that no objects were leaked.
//
// TODO: This test is very brittle, depending on current JDK
// implementation, and needing occasional adjustment.
System.out.printf("%d -> %d%n", n0, n1);
// Almost always n0 == n1
! // Maximum jitter observed in practice is 10 -> 17
check(Math.abs(n1 - n0) < 10);
check(n1 < 25);
drainers.shutdown();
if (!drainers.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) {
drainers.shutdownNow(); // last resort
--- 175,240 ----
s.flush();
}
static int objectsInUse(final Process child,
final String childPid,
! final String classNameRegex) {
! String regex =
! "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +"+classNameRegex+"(?:$| )";
! Callable<Integer> objectsInUse = () -> {
! int i = Integer.parseInt(
! match(commandOutputOf(jmapPath, "-histo:live", childPid),
regex, 1));
if (i > 100)
System.out.print(
! commandOutputOf(jmapPath,
"-dump:file=dump,format=b",
childPid));
return i;
! };
try { return rendezvousParent(child, objectsInUse); }
catch (Throwable t) { unexpected(t); return -1; }
}
static void realMain(String[] args) throws Throwable {
// jmap doesn't work on Windows
if (System.getProperty("os.name").startsWith("Windows"))
return;
final String childClassName = Job.class.getName();
! final String classNameRegex = Job.classNameRegexToCheckForLeaks();
! final String uniqueID = String.valueOf(
! ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE));
!
! final ArrayList<String> jobCmd = new ArrayList<>();
! Collections.addAll(
! jobCmd, javaPath, "-Xmx8m", "-XX:+UsePerfData",
! "-classpath", System.getProperty("test.class.path"));
! Collections.addAll(jobCmd, Utils.getTestJavaOpts());
! Collections.addAll(jobCmd, childClassName, uniqueID);
final Process p = new ProcessBuilder(jobCmd).start();
// Ensure subprocess jvm has started, so that jps can find it
p.getInputStream().read();
sendByte(p.getOutputStream());
final String childPid =
! match(commandOutputOf(jpsPath, "-m"),
"(?m)^ *([0-9]+) +\\Q"+childClassName+"\\E *"+uniqueID+"$", 1);
! final int n0 = objectsInUse(p, childPid, classNameRegex);
! final int n1 = objectsInUse(p, childPid, classNameRegex);
equal(p.waitFor(), 0);
equal(p.exitValue(), 0);
failed += p.exitValue();
// Check that no objects were leaked.
//
// TODO: This test is very brittle, depending on current JDK
// implementation, and needing occasional adjustment.
System.out.printf("%d -> %d%n", n0, n1);
// Almost always n0 == n1
! // Maximum jitter observed in practice is 7
check(Math.abs(n1 - n0) < 10);
check(n1 < 25);
drainers.shutdown();
if (!drainers.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) {
drainers.shutdownNow(); // last resort
*** 242,254 ****
// - provide the name of a class to check for leaks.
// - call rendezvousChild exactly twice, while quiescent.
// - in between calls to rendezvousChild, run code that may leak.
//----------------------------------------------------------------
public static class Job {
! static String classToCheckForLeaks() {
return
! "java.util.concurrent.locks.AbstractQueuedSynchronizer$Node";
}
public static void main(String[] args) throws Throwable {
// Synchronize with parent process, so that jps can find us
sendByte(System.out);
--- 248,260 ----
// - provide the name of a class to check for leaks.
// - call rendezvousChild exactly twice, while quiescent.
// - in between calls to rendezvousChild, run code that may leak.
//----------------------------------------------------------------
public static class Job {
! static String classNameRegexToCheckForLeaks() {
return
! "\\Qjava.util.concurrent.locks.AbstractQueuedSynchronizer$\\E[A-Za-z]+";
}
public static void main(String[] args) throws Throwable {
// Synchronize with parent process, so that jps can find us
sendByte(System.out);
< prev index next >