6977426: sun/tools tests can intermittently fail to find app's Java pid
Reviewed-by: dfuchs, jbachorik, egahlin, sjiang
--- a/jdk/test/TEST.groups Wed Dec 17 12:29:20 2014 -0800
+++ b/jdk/test/TEST.groups Fri Dec 19 13:13:11 2014 +0100
@@ -421,8 +421,7 @@
java/util/Collections/EmptyIterator.java \
java/util/concurrent/locks/Lock/TimedAcquireLeak.java \
java/util/jar/JarInputStream/ExtraFileInMetaInf.java \
- java/util/logging/AnonLoggerWeakRefLeak.sh \
- java/util/logging/LoggerWeakRefLeak.sh \
+ java/util/logging/TestLoggerWeakRefLeak.java \
java/util/zip/3GBZipFiles.sh \
jdk/lambda/FDTest.java \
jdk/lambda/separate/Compiler.java \
--- a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java Wed Dec 17 12:29:20 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2010, 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.logging.*;
-
-public class AnonLoggerWeakRefLeak extends SimpleApplication {
- // The test driver script will allow this program to run until we
- // reach DEFAULT_LOOP_TIME or a decrease in instance counts is
- // observed. For this particular WeakReference leak, the count
- // was always observed to be increasing so if we get a decreasing
- // count, then the leak is fixed in the bits being tested.
- // Two minutes has been enough time to observe a decrease in
- // fixed bits on overloaded systems, but the test will likely
- // finish more quickly.
- public static int DEFAULT_LOOP_TIME = 120; // time is in seconds
-
- // execute the AnonLoggerWeakRefLeak app work
- public void doMyAppWork(String[] args) throws Exception {
- int loop_time = 0;
- int max_loop_time = DEFAULT_LOOP_TIME;
-
- // args[0] is the port-file
- if (args.length < 2) {
- System.out.println("INFO: using default time of "
- + max_loop_time + " seconds.");
- } else {
- try {
- max_loop_time = Integer.parseInt(args[1]);
- } catch (NumberFormatException nfe) {
- throw new RuntimeException("Error: '" + args[1]
- + "': is not a valid seconds value.");
- }
- }
-
- long count = 0;
- long now = 0;
- long startTime = System.currentTimeMillis();
-
- while (now < (startTime + (max_loop_time * 1000))) {
- if ((count % 1000) == 0) {
- // Print initial call count to let caller know that
- // we're up and running and then periodically
- System.out.println("INFO: call count = " + count);
- }
-
- for (int i = 0; i < 100; i++) {
- // this Logger call is leaking a WeakReference in Logger.kids
- java.util.logging.Logger.getAnonymousLogger();
- count++;
- }
-
- try {
- // delay for 1/10 of a second to avoid CPU saturation
- Thread.sleep(100);
- } catch (InterruptedException ie) {
- // ignore any exceptions
- }
-
- now = System.currentTimeMillis();
- }
-
- System.out.println("INFO: final loop count = " + count);
- }
-
- public static void main(String[] args) throws Exception {
- AnonLoggerWeakRefLeak myApp = new AnonLoggerWeakRefLeak();
-
- SimpleApplication.setMyApp(myApp);
-
- SimpleApplication.main(args);
- }
-}
--- a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh Wed Dec 17 12:29:20 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2010, 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 6942989
-# @summary Check for WeakReference leak in anonymous Logger objects
-# @author Daniel D. Daugherty
-#
-# @library ../../../sun/tools/common
-# @build SimpleApplication ShutdownSimpleApplication
-# @build AnonLoggerWeakRefLeak
-# @run shell/timeout=240 AnonLoggerWeakRefLeak.sh
-
-# The timeout is: 2 minutes for infrastructure and 2 minutes for the test
-#
-
-. ${TESTSRC}/../../../sun/tools/common/CommonSetup.sh
-. ${TESTSRC}/../../../sun/tools/common/ApplicationSetup.sh
-
-
-TEST_NAME="AnonLoggerWeakRefLeak"
-TARGET_CLASS="java\.lang\.ref\.WeakReference"
-
-
-# MAIN begins here
-#
-
-seconds=
-if [ "$#" -gt 0 ]; then
- seconds="$1"
-fi
-
-# see if this version of jmap supports the '-histo:live' option
-jmap_option="-histo:live"
-set +e
-"${JMAP}" 2>&1 | grep ':live' > /dev/null 2>&1
-status="$?"
-set -e
-if [ "$status" != 0 ]; then
- # usage message doesn't show ':live' option
-
- if $isWindows; then
- # If SA isn't present, then jmap gives a different usage message
- # that doesn't show the ':live' option. However, that's a bug that
- # is covered by 6971851 so we try using the option just to be sure.
- # For some reason, this problem has only been seen on OpenJDK6 on
- # Windows. Not sure why.
- set +e
- # Note: Don't copy this code to try probing process 0 on Linux; it
- # will kill the process group in strange ways.
- "${JMAP}" "$jmap_option" 0 2>&1 | grep 'Usage' > /dev/null 2>&1
- status="$?"
- set -e
- if [ "$status" = 0 ]; then
- # Usage message generated so flag the problem.
- status=1
- else
- # No usage message so clear the flag.
- status=0
- fi
- fi
-
- if [ "$status" != 0 ]; then
- echo "WARNING: 'jmap $jmap_option' is not supported on this platform"
- echo "WARNING: so this test cannot work reliably. Aborting!"
- exit 0
- fi
-fi
-
-# Start application and use TEST_NAME.port for coordination
-startApplication "$TEST_NAME" "$TEST_NAME.port" $seconds
-
-finished_early=false
-
-decreasing_cnt=0
-increasing_cnt=0
-loop_cnt=0
-prev_instance_cnt=0
-
-MAX_JMAP_TRY_CNT=10
-jmap_retry_cnt=0
-loop_cnt_on_retry=0
-
-while true; do
- # see if the target process has finished its run and bail if it has
- set +e
- grep "^INFO: final loop count = " "$appOutput" > /dev/null 2>&1
- status="$?"
- set -e
- if [ "$status" = 0 ]; then
- break
- fi
-
- # Output format for 'jmap -histo' in JDK1.5.0:
- #
- # <#bytes> <#instances> <class_name>
- #
- # Output format for 'jmap -histo:live':
- #
- # <num>: <#instances> <#bytes> <class_name>
- #
- set +e
- "${JMAP}" "$jmap_option" "$appJavaPid" > "$TEST_NAME.jmap" 2>&1
- status="$?"
- set -e
-
- if [ "$status" != 0 ]; then
- echo "INFO: jmap exited with exit code = $status"
-
- # There are intermittent jmap failures; see 6498448.
- #
- # So far the following have been observed in a jmap call
- # that was not in a race with target process termination:
- #
- # (Solaris specific, 2nd sample)
- # <pid>: Unable to open door: target process not responding or HotSpot VM not loaded
- # The -F option can be used when the target process is not responding
- #
- # (on Solaris so far)
- # java.io.IOException
- #
- # (on Solaris so far, 1st sample)
- # <pid>: Permission denied
- #
- sed 's/^/INFO: /' "$TEST_NAME.jmap"
-
- if [ "$loop_cnt" = "$loop_cnt_on_retry" ]; then
- # loop count hasn't changed
- jmap_retry_cnt=`expr $jmap_retry_cnt + 1`
- else
- # loop count has changed so remember it
- jmap_retry_cnt=1
- loop_cnt_on_retry="$loop_cnt"
- fi
-
- # This is '-ge' because we have the original attempt plus
- # MAX_JMAP_TRY_CNT - 1 retries.
- if [ "$jmap_retry_cnt" -ge "$MAX_JMAP_TRY_CNT" ]; then
- echo "INFO: jmap failed $MAX_JMAP_TRY_CNT times in a row" \
- "without making any progress."
- echo "FAIL: jmap is unable to take any samples." >&2
- killApplication
- exit 2
- fi
-
- # short delay and try again
- # Note: sleep 1 didn't help with "<pid>: Permission denied"
- sleep 2
- echo "INFO: retrying jmap (retry=$jmap_retry_cnt, loop=$loop_cnt)."
- continue
- fi
-
- set +e
- instance_cnt=`grep "${PATTERN_WS}${TARGET_CLASS}${PATTERN_EOL}" \
- "$TEST_NAME.jmap" \
- | sed '
- # strip leading whitespace; does nothing in JDK1.5.0
- s/^'"${PATTERN_WS}${PATTERN_WS}"'*//
- # strip <#bytes> in JDK1.5.0; does nothing otherwise
- s/^[1-9][0-9]*'"${PATTERN_WS}${PATTERN_WS}"'*//
- # strip <num>: field; does nothing in JDK1.5.0
- s/^[1-9][0-9]*:'"${PATTERN_WS}${PATTERN_WS}"'*//
- # strip <class_name> field
- s/'"${PATTERN_WS}"'.*//
- '`
- set -e
- if [ -z "$instance_cnt" ]; then
- echo "INFO: instance count is unexpectedly empty"
- if [ "$loop_cnt" = 0 ]; then
- echo "INFO: on the first iteration so no sample was found."
- echo "INFO: There is likely a problem with the sed filter."
- echo "INFO: start of jmap output:"
- cat "$TEST_NAME.jmap"
- echo "INFO: end of jmap output."
- echo "FAIL: cannot find the instance count value." >&2
- killApplication
- exit 2
- fi
- else
- echo "INFO: instance_cnt = $instance_cnt"
-
- if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then
- increasing_cnt=`expr $increasing_cnt + 1`
- else
- # actually decreasing or the same
- decreasing_cnt=`expr $decreasing_cnt + 1`
-
- # For this particular WeakReference leak, the count was
- # always observed to be increasing so if we get a decreasing
- # or the same count, then the leak is fixed in the bits
- # being tested.
- echo "INFO: finishing early due to non-increasing instance count."
- finished_early=true
- killApplication
- break
- fi
- prev_instance_cnt="$instance_cnt"
- fi
-
- # delay between samples
- sleep 5
-
- loop_cnt=`expr $loop_cnt + 1`
-done
-
-if [ $finished_early = false ]; then
- stopApplication "$TEST_NAME.port"
- waitForApplication
-fi
-
-echo "INFO: $TEST_NAME has finished running."
-echo "INFO: increasing_cnt = $increasing_cnt"
-echo "INFO: decreasing_cnt = $decreasing_cnt"
-if [ "$jmap_retry_cnt" -gt 0 ]; then
- echo "INFO: jmap_retry_cnt = $jmap_retry_cnt (in $loop_cnt iterations)"
-fi
-
-if [ "$loop_cnt" = 0 ]; then
- echo "FAIL: jmap is unable to take any samples." >&2
- exit 2
-fi
-
-echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects"
-if [ "$decreasing_cnt" = 0 ]; then
- echo "INFO: is always increasing."
- echo "FAIL: This indicates that there is a memory leak." >&2
- exit 2
-fi
-
-echo "INFO: is not always increasing."
-echo "PASS: This indicates that there is not a memory leak."
-exit 0
--- a/jdk/test/java/util/logging/LoggerWeakRefLeak.java Wed Dec 17 12:29:20 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2010, 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.logging.*;
-
-public class LoggerWeakRefLeak extends SimpleApplication {
- // The test driver script will allow this program to run until we
- // reach DEFAULT_LOOP_TIME or a decrease in instance counts is
- // observed. For these particular WeakReference leaks, the count
- // was always observed to be increasing so if we get a decreasing
- // count, then the leaks are fixed in the bits being tested.
- // Two minutes has been enough time to observe a decrease in
- // fixed bits on overloaded systems, but the test will likely
- // finish more quickly.
- public static int DEFAULT_LOOP_TIME = 120; // time is in seconds
-
- // execute the LoggerWeakRefLeak app work
- public void doMyAppWork(String[] args) throws Exception {
- int loop_time = 0;
- int max_loop_time = DEFAULT_LOOP_TIME;
-
- // args[0] is the port-file
- if (args.length < 2) {
- System.out.println("INFO: using default time of "
- + max_loop_time + " seconds.");
- } else {
- try {
- max_loop_time = Integer.parseInt(args[1]);
- } catch (NumberFormatException nfe) {
- throw new RuntimeException("Error: '" + args[1]
- + "': is not a valid seconds value.");
- }
- }
-
- long count = 0;
- int loggerCount = 0;
- long now = 0;
- long startTime = System.currentTimeMillis();
-
- while (now < (startTime + (max_loop_time * 1000))) {
- if ((count % 1000) == 0) {
- // Print initial call count to let caller know that
- // we're up and running and then periodically
- System.out.println("INFO: call count = " + count);
- }
-
- for (int i = 0; i < 100; i++) {
- // This Logger call is leaking two different WeakReferences:
- // - one in LogManager.LogNode
- // - one in Logger.kids
- java.util.logging.Logger.getLogger("logger-" + loggerCount);
- count++;
- if (++loggerCount >= 25000) {
- // Limit the Logger namespace used by the test so
- // the weak refs in LogManager.loggers that are
- // being properly managed don't skew the counts
- // by too much.
- loggerCount = 0;
- }
- }
-
- try {
- // delay for 1/10 of a second to avoid CPU saturation
- Thread.sleep(100);
- } catch (InterruptedException ie) {
- // ignore any exceptions
- }
-
- now = System.currentTimeMillis();
- }
-
- System.out.println("INFO: final loop count = " + count);
- }
-
- public static void main(String[] args) throws Exception {
- AnonLoggerWeakRefLeak myApp = new AnonLoggerWeakRefLeak();
-
- SimpleApplication.setMyApp(myApp);
-
- SimpleApplication.main(args);
- }
-}
--- a/jdk/test/java/util/logging/LoggerWeakRefLeak.sh Wed Dec 17 12:29:20 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2010, 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 6942989
-# @summary Check for WeakReference leak in Logger objects
-# @author Daniel D. Daugherty
-#
-# @library ../../../sun/tools/common
-# @build SimpleApplication ShutdownSimpleApplication
-# @build LoggerWeakRefLeak
-# @run shell/timeout=240 LoggerWeakRefLeak.sh
-
-# The timeout is: 2 minutes for infrastructure and 2 minutes for the test
-#
-
-. ${TESTSRC}/../../../sun/tools/common/CommonSetup.sh
-. ${TESTSRC}/../../../sun/tools/common/ApplicationSetup.sh
-
-
-TEST_NAME="LoggerWeakRefLeak"
-TARGET_CLASS="java\.lang\.ref\.WeakReference"
-
-
-# MAIN begins here
-#
-
-seconds=
-if [ "$#" -gt 0 ]; then
- seconds="$1"
-fi
-
-# see if this version of jmap supports the '-histo:live' option
-jmap_option="-histo:live"
-set +e
-"${JMAP}" 2>&1 | grep ':live' > /dev/null 2>&1
-status="$?"
-set -e
-if [ "$status" != 0 ]; then
- # usage message doesn't show ':live' option
-
- if $isWindows; then
- # If SA isn't present, then jmap gives a different usage message
- # that doesn't show the ':live' option. However, that's a bug that
- # is covered by 6971851 so we try using the option just to be sure.
- # For some reason, this problem has only been seen on OpenJDK6 on
- # Windows. Not sure why.
- set +e
- # Note: Don't copy this code to try probing process 0 on Linux; it
- # will kill the process group in strange ways.
- "${JMAP}" "$jmap_option" 0 2>&1 | grep 'Usage' > /dev/null 2>&1
- status="$?"
- set -e
- if [ "$status" = 0 ]; then
- # Usage message generated so flag the problem.
- status=1
- else
- # No usage message so clear the flag.
- status=0
- fi
- fi
-
- if [ "$status" != 0 ]; then
- echo "WARNING: 'jmap $jmap_option' is not supported on this platform"
- echo "WARNING: so this test cannot work reliably. Aborting!"
- exit 0
- fi
-fi
-
-# Start application and use TEST_NAME.port for coordination
-startApplication "$TEST_NAME" "$TEST_NAME.port" $seconds
-
-finished_early=false
-
-decreasing_cnt=0
-increasing_cnt=0
-loop_cnt=0
-prev_instance_cnt=0
-
-MAX_JMAP_TRY_CNT=10
-jmap_retry_cnt=0
-loop_cnt_on_retry=0
-
-while true; do
- # see if the target process has finished its run and bail if it has
- set +e
- grep "^INFO: final loop count = " "$appOutput" > /dev/null 2>&1
- status="$?"
- set -e
- if [ "$status" = 0 ]; then
- break
- fi
-
- # Output format for 'jmap -histo' in JDK1.5.0:
- #
- # <#bytes> <#instances> <class_name>
- #
- # Output format for 'jmap -histo:live':
- #
- # <num>: <#instances> <#bytes> <class_name>
- #
- set +e
- "${JMAP}" "$jmap_option" "$appJavaPid" > "$TEST_NAME.jmap" 2>&1
- status="$?"
- set -e
-
- if [ "$status" != 0 ]; then
- echo "INFO: jmap exited with exit code = $status"
-
- # There are intermittent jmap failures; see 6498448.
- #
- # So far the following have been observed in a jmap call
- # that was not in a race with target process termination:
- #
- # (Solaris specific, 2nd sample)
- # <pid>: Unable to open door: target process not responding or HotSpot VM not loaded
- # The -F option can be used when the target process is not responding
- #
- # (on Solaris so far)
- # java.io.IOException
- #
- # (on Solaris so far, 1st sample)
- # <pid>: Permission denied
- #
- sed 's/^/INFO: /' "$TEST_NAME.jmap"
-
- if [ "$loop_cnt" = "$loop_cnt_on_retry" ]; then
- # loop count hasn't changed
- jmap_retry_cnt=`expr $jmap_retry_cnt + 1`
- else
- # loop count has changed so remember it
- jmap_retry_cnt=1
- loop_cnt_on_retry="$loop_cnt"
- fi
-
- # This is '-ge' because we have the original attempt plus
- # MAX_JMAP_TRY_CNT - 1 retries.
- if [ "$jmap_retry_cnt" -ge "$MAX_JMAP_TRY_CNT" ]; then
- echo "INFO: jmap failed $MAX_JMAP_TRY_CNT times in a row" \
- "without making any progress."
- echo "FAIL: jmap is unable to take any samples." >&2
- killApplication
- exit 2
- fi
-
- # short delay and try again
- # Note: sleep 1 didn't help with "<pid>: Permission denied"
- sleep 2
- echo "INFO: retrying jmap (retry=$jmap_retry_cnt, loop=$loop_cnt)."
- continue
- fi
-
- set +e
- instance_cnt=`grep "${PATTERN_WS}${TARGET_CLASS}${PATTERN_EOL}" \
- "$TEST_NAME.jmap" \
- | sed '
- # strip leading whitespace; does nothing in JDK1.5.0
- s/^'"${PATTERN_WS}${PATTERN_WS}"'*//
- # strip <#bytes> in JDK1.5.0; does nothing otherwise
- s/^[1-9][0-9]*'"${PATTERN_WS}${PATTERN_WS}"'*//
- # strip <num>: field; does nothing in JDK1.5.0
- s/^[1-9][0-9]*:'"${PATTERN_WS}${PATTERN_WS}"'*//
- # strip <class_name> field
- s/'"${PATTERN_WS}"'.*//
- '`
- set -e
- if [ -z "$instance_cnt" ]; then
- echo "INFO: instance count is unexpectedly empty"
- if [ "$loop_cnt" = 0 ]; then
- echo "INFO: on the first iteration so no sample was found."
- echo "INFO: There is likely a problem with the sed filter."
- echo "INFO: start of jmap output:"
- cat "$TEST_NAME.jmap"
- echo "INFO: end of jmap output."
- echo "FAIL: cannot find the instance count value." >&2
- killApplication
- exit 2
- fi
- else
- echo "INFO: instance_cnt = $instance_cnt"
-
- if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then
- increasing_cnt=`expr $increasing_cnt + 1`
- else
- # actually decreasing or the same
- decreasing_cnt=`expr $decreasing_cnt + 1`
-
- # For these particular WeakReference leaks, the count was
- # always observed to be increasing so if we get a decreasing
- # or the same count, then the leaks are fixed in the bits
- # being tested.
- echo "INFO: finishing early due to non-increasing instance count."
- finished_early=true
- killApplication
- break
- fi
- prev_instance_cnt="$instance_cnt"
- fi
-
- # delay between samples
- sleep 5
-
- loop_cnt=`expr $loop_cnt + 1`
-done
-
-if [ $finished_early = false ]; then
- stopApplication "$TEST_NAME.port"
- waitForApplication
-fi
-
-echo "INFO: $TEST_NAME has finished running."
-echo "INFO: increasing_cnt = $increasing_cnt"
-echo "INFO: decreasing_cnt = $decreasing_cnt"
-if [ "$jmap_retry_cnt" -gt 0 ]; then
- echo "INFO: jmap_retry_cnt = $jmap_retry_cnt (in $loop_cnt iterations)"
-fi
-
-if [ "$loop_cnt" = 0 ]; then
- echo "FAIL: jmap is unable to take any samples." >&2
- exit 2
-fi
-
-echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects"
-if [ "$decreasing_cnt" = 0 ]; then
- echo "INFO: is always increasing."
- echo "FAIL: This indicates that there is a memory leak." >&2
- exit 2
-fi
-
-echo "INFO: is not always increasing."
-echo "PASS: This indicates that there is not a memory leak."
-exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/TestLoggerWeakRefLeak.java Fri Dec 19 13:13:11 2014 +0100
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2010, 2014, 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.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import static jdk.testlibrary.Asserts.assertGreaterThan;
+import jdk.testlibrary.ProcessTools;
+
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.VirtualMachine;
+
+import sun.tools.attach.HotSpotVirtualMachine;
+
+/*
+ * @test
+ * @bug 6942989
+ * @summary Check for WeakReference leak in Logger and anonymous Logger objects
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @run main/othervm TestLoggerWeakRefLeak Logger
+ * @run main/othervm TestLoggerWeakRefLeak AnonymousLogger
+ */
+public class TestLoggerWeakRefLeak {
+
+ private static final String TARGET_CLASS = "java.lang.ref.WeakReference";
+ private static final int INSTANCE_COUNT = 100;
+ private static int loggerCount = 0;
+
+ public static void main(String[] args) throws Exception {
+ if (args[0].equals("AnonymousLogger")) {
+ System.out.println("Test for WeakReference leak in AnonymousLogger object");
+ testIfLeaking(TestLoggerWeakRefLeak::callAnonymousLogger);
+ } else {
+ System.out.println("Test for WeakReference leak in Logger object");
+ testIfLeaking(TestLoggerWeakRefLeak::callLogger);
+ }
+ }
+
+ /**
+ * For these particular WeakReference leaks, the count was always observed
+ * to be increasing so if decreasing or the same count is observed,
+ * then there is no leak.
+ */
+ private static void testIfLeaking(Runnable callLogger) throws Exception {
+ long count = 0;
+ int instanceCount = 0;
+ int previousInstanceCount = 0;
+ int increasingCount = 0;
+ int decreasingCount = 0;
+
+ while (true) {
+ callLogger.run();
+ count += INSTANCE_COUNT;
+
+ if ((count % 1000) == 0) {
+ System.out.println("call count = " + count);
+
+ instanceCount = getInstanceCountFromHeapHisto();
+ if (instanceCount > previousInstanceCount) {
+ increasingCount++;
+ } else {
+ decreasingCount++;
+ System.out.println("increasing count: " + increasingCount);
+ System.out.println("decreasing or the same count: " + decreasingCount);
+ System.out.println("Test passed: decreasing or the same instance count is observed");
+ break;
+ }
+ previousInstanceCount = instanceCount;
+ }
+
+ delayExecution();
+ }
+ }
+
+ /**
+ * This Logger call is leaking two different WeakReferences:
+ * - one in LogManager.LogNode
+ * - one in Logger.kids
+ */
+ private static void callLogger() {
+ for (int i = 0; i < INSTANCE_COUNT; i++) {
+ java.util.logging.Logger.getLogger("logger-" + loggerCount);
+ if (++loggerCount >= 25000) {
+ // Limit the Logger namespace used by the test so the weak refs
+ // in LogManager.loggers that are being properly managed
+ // don't skew the counts by too much.
+ loggerCount = 0;
+ }
+ }
+ }
+
+ /**
+ * This Logger call is leaking a WeakReference in Logger.kids
+ */
+ private static void callAnonymousLogger() {
+ for (int i = 0; i < INSTANCE_COUNT; i++) {
+ java.util.logging.Logger.getAnonymousLogger();
+ }
+ }
+
+ /**
+ * 'vm.heapHisto("-live")' will request a full GC
+ */
+ private static int getInstanceCountFromHeapHisto() throws AttachNotSupportedException, Exception {
+ int instanceCount = 0;
+
+ HotSpotVirtualMachine vm = (HotSpotVirtualMachine) VirtualMachine
+ .attach(Integer.toString(ProcessTools.getProcessId()));
+ try {
+ try (InputStream heapHistoStream = vm.heapHisto("-live");
+ BufferedReader in = new BufferedReader(new InputStreamReader(heapHistoStream))) {
+ String inputLine;
+ while ((inputLine = in.readLine()) != null) {
+ if (inputLine.contains(TARGET_CLASS)) {
+ instanceCount = Integer.parseInt(inputLine
+ .split("[ ]+")[2]);
+ System.out.println("instance count: " + instanceCount);
+ break;
+ }
+ }
+ }
+ } finally {
+ vm.detach();
+ }
+
+ assertGreaterThan(instanceCount, 0, "No instances of " + TARGET_CLASS + " are found");
+
+ return instanceCount;
+ }
+
+ /**
+ * Delay for 1/10 of a second to avoid CPU saturation
+ */
+ private static void delayExecution() {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ie) {
+ // Ignore any exceptions
+ }
+ }
+
+}
--- a/jdk/test/sun/tools/common/CommonTests.sh Wed Dec 17 12:29:20 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2010, 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 6964018
-# @summary Unit test for common tools infrastructure.
-#
-# @build SimpleApplication SleeperApplication ShutdownSimpleApplication
-# @run shell CommonTests.sh
-
-. ${TESTSRC}/CommonSetup.sh
-. ${TESTSRC}/ApplicationSetup.sh
-
-# hope for the best:
-status=0
-
-
-# Test program path constants from CommonSetup.sh:
-#
-for name in JAVA JHAT JINFO JMAP JPS JSTACK; do
- eval value=$`echo $name`
-
- echo "INFO: $name=$value"
- if [ -x "$value" ]; then
- echo "INFO: '$value' is executable."
- else
- echo "ERROR: '$value' is not executable." >&2
- status=1
- fi
-done
-
-
-# Display flag values from CommonSetup.sh:
-#
-for name in isCygwin isMKS isLinux isSolaris isUnknownOS isWindows; do
- eval value=$`echo $name`
- echo "INFO: flag $name=$value"
-done
-
-
-# Test OS constant from CommonSetup.sh:
-#
-if [ -z "$OS" ]; then
- echo "ERROR: OS constant cannot be empty." >&2
- status=1
-fi
-
-
-# Display the PATTERN_EOL value:
-#
-echo "INFO: PATTERN_EOL="`echo "$PATTERN_EOL" | od -c`
-
-
-# Test PATTERN_EOL with 'grep' for a regular line.
-#
-TESTOUT="${TESTCLASSES}/testout.grep_reg_line_eol"
-set +e
-echo 'regular line' | grep "line${PATTERN_EOL}" > "$TESTOUT"
-set -e
-if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_EOL works for regular line with grep."
-else
- echo "ERROR: PATTERN_EOL does not work for regular line with grep." >&2
- status=1
-fi
-
-
-if $isWindows; then
- # Test PATTERN_EOL with 'grep' for a CR line.
- #
- TESTOUT="${TESTCLASSES}/testout.grep_cr_line_eol"
- set +e
- echo 'CR line
' | grep "line${PATTERN_EOL}" > "$TESTOUT"
- set -e
- if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_EOL works for CR line with grep."
- else
- echo "ERROR: PATTERN_EOL does not work for CR line with grep." >&2
- status=1
- fi
-fi
-
-
-# Test PATTERN_EOL with 'sed' for a regular line.
-#
-TESTOUT="${TESTCLASSES}/testout.sed_reg_line_eol"
-echo 'regular line' | sed -n "/line${PATTERN_EOL}/p" > "$TESTOUT"
-if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_EOL works for regular line with sed."
-else
- echo "ERROR: PATTERN_EOL does not work for regular line with sed." >&2
- status=1
-fi
-
-
-if $isWindows; then
- # Test PATTERN_EOL with 'sed' for a CR line.
- #
- TESTOUT="${TESTCLASSES}/testout.sed_cr_line_eol"
- echo 'CR line
' | sed -n "/line${PATTERN_EOL}/p" > "$TESTOUT"
- if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_EOL works for CR line with sed."
- else
- echo "ERROR: PATTERN_EOL does not work for CR line with sed." >&2
- status=1
- fi
-fi
-
-
-# Display the PATTERN_WS value:
-#
-echo "INFO: PATTERN_WS="`echo "$PATTERN_WS" | od -c`
-
-
-# Test PATTERN_WS with 'grep' for a blank.
-#
-TESTOUT="${TESTCLASSES}/testout.grep_blank"
-set +e
-echo 'blank: ' | grep "$PATTERN_WS" > "$TESTOUT"
-set -e
-if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_WS works for blanks with grep."
-else
- echo "ERROR: PATTERN_WS does not work for blanks with grep." >&2
- status=1
-fi
-
-
-# Test PATTERN_WS with 'grep' for a tab.
-#
-TESTOUT="${TESTCLASSES}/testout.grep_tab"
-set +e
-echo 'tab: ' | grep "$PATTERN_WS" > "$TESTOUT"
-set -e
-if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_WS works for tabs with grep."
-else
- echo "ERROR: PATTERN_WS does not work for tabs with grep." >&2
- status=1
-fi
-
-
-# Test PATTERN_WS with 'sed' for a blank.
-#
-TESTOUT="${TESTCLASSES}/testout.sed_blank"
-echo 'blank: ' | sed -n "/$PATTERN_WS/p" > "$TESTOUT"
-if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_WS works for blanks with sed."
-else
- echo "ERROR: PATTERN_WS does not work for blanks with sed." >&2
- status=1
-fi
-
-
-# Test PATTERN_WS with 'sed' for a tab.
-#
-TESTOUT="${TESTCLASSES}/testout.sed_tab"
-echo 'tab: ' | sed -n "/$PATTERN_WS/p" > "$TESTOUT"
-if [ -s "$TESTOUT" ]; then
- echo "INFO: PATTERN_WS works for tabs with sed."
-else
- echo "ERROR: PATTERN_WS does not work for tabs with sed." >&2
- status=1
-fi
-
-
-# Test startApplication and use PORTFILE for coordination
-# The app sleeps for 30 seconds.
-#
-PORTFILE="${TESTCLASSES}"/shutdown.port
-startApplication SleeperApplication "${PORTFILE}" 30
-
-
-# Test appJavaPid in "ps" cmd output.
-#
-TESTOUT="${TESTCLASSES}/testout.ps_app"
-set +e
-if $isCygwin; then
- # On Cygwin, appJavaPid is the Windows pid for the Java process
- # and appOtherPid is the Cygwin pid for the Java process.
- ps -p "$appOtherPid" \
- | grep "${PATTERN_WS}${appJavaPid}${PATTERN_WS}" > "$TESTOUT"
-else
- # output only pid and comm columns to avoid mismatches
- ps -eo pid,comm \
- | grep "^${PATTERN_WS}*${appJavaPid}${PATTERN_WS}" > "$TESTOUT"
-fi
-set -e
-if [ -s "$TESTOUT" ]; then
- echo "INFO: begin appJavaPid=$appJavaPid in 'ps' cmd output:"
- cat "$TESTOUT"
- echo "INFO: end appJavaPid=$appJavaPid in 'ps' cmd output."
-else
- echo "ERROR: 'ps' cmd should show appJavaPid=$appJavaPid." >&2
- status=1
-fi
-
-if [ -n "$appOtherPid" ]; then
- # Test appOtherPid in "ps" cmd output, if we have one.
- #
- TESTOUT="${TESTCLASSES}/testout.ps_other"
- set +e
- if $isCygwin; then
- ps -p "$appOtherPid" \
- | grep "${PATTERN_WS}${appOtherPid}${PATTERN_WS}" > "$TESTOUT"
- else
- # output only pid and comm columns to avoid mismatches
- ps -eo pid,comm \
- | grep "^${PATTERN_WS}*${appOtherPid}${PATTERN_WS}" > "$TESTOUT"
- fi
- set -e
- if [ -s "$TESTOUT" ]; then
- echo "INFO: begin appOtherPid=$appOtherPid in 'ps' cmd output:"
- cat "$TESTOUT"
- echo "INFO: end appOtherPid=$appOtherPid in 'ps' cmd output."
- else
- echo "ERROR: 'ps' cmd should show appOtherPid=$appOtherPid." >&2
- status=1
- fi
-fi
-
-
-# Test stopApplication and PORTFILE for coordination
-#
-stopApplication "${PORTFILE}"
-
-
-# Test application still running after stopApplication.
-#
-# stopApplication just lets the app know that it can stop, but the
-# app might still be doing work. This test just demonstrates that
-# fact and doesn't fail if the app is already done.
-#
-TESTOUT="${TESTCLASSES}/testout.after_stop"
-set +e
-if $isCygwin; then
- # On Cygwin, appJavaPid is the Windows pid for the Java process
- # and appOtherPid is the Cygwin pid for the Java process.
- ps -p "$appOtherPid" \
- | grep "${PATTERN_WS}${appJavaPid}${PATTERN_WS}" > "$TESTOUT"
-else
- # output only pid and comm columns to avoid mismatches
- ps -eo pid,comm \
- | grep "^${PATTERN_WS}*${appJavaPid}${PATTERN_WS}" > "$TESTOUT"
-fi
-set -e
-if [ -s "$TESTOUT" ]; then
- echo "INFO: it is okay for appJavaPid=$appJavaPid to still be running" \
- "after stopApplication() is called."
- echo "INFO: begin 'after_stop' output:"
- cat "$TESTOUT"
- echo "INFO: end 'after_stop' output."
-fi
-
-
-# Test waitForApplication
-#
-# The app might already be gone so this function shouldn't generate
-# a fatal error in either call.
-#
-waitForApplication
-
-if [ $isWindows = false ]; then
- # Windows can recycle pids quickly so we can't use this test there
- TESTOUT="${TESTCLASSES}/testout.after_kill"
- set +e
- # output only pid and comm columns to avoid mismatches
- ps -eo pid,comm \
- | grep "^${PATTERN_WS}*${appJavaPid}${PATTERN_WS}" > "$TESTOUT"
- set -e
- if [ -s "$TESTOUT" ]; then
- echo "ERROR: 'ps' cmd should not show appJavaPid." >&2
- echo "ERROR: begin 'after_kill' output:" >&2
- cat "$TESTOUT" >&2
- echo "ERROR: end 'after_kill' output." >&2
- status=1
- else
- echo "INFO: 'ps' cmd does not show appJavaPid after" \
- "waitForApplication() is called."
- fi
-fi
-
-
-# Test killApplication
-#
-# The app is already be gone so this function shouldn't generate
-# a fatal error.
-#
-killApplication
-
-exit $status