# HG changeset patch # User minqi # Date 1419452611 0 # Node ID 022799a053fedd52adfc277825b13f3d878194ab # Parent 4673729e145d7480291f0c2a4d84c9902cf06112# Parent a928e15e8273a323a6ec5024c57281b04356cdcb Merge diff -r 4673729e145d -r 022799a053fe jdk/test/TEST.groups --- a/jdk/test/TEST.groups Tue Dec 23 12:40:06 2014 -0800 +++ b/jdk/test/TEST.groups Wed Dec 24 20:23:31 2014 +0000 @@ -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 \ diff -r 4673729e145d -r 022799a053fe jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java --- a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java Tue Dec 23 12:40:06 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); - } -} diff -r 4673729e145d -r 022799a053fe jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh --- a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh Tue Dec 23 12:40:06 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> - # - # Output format for 'jmap -histo:live': - # - # : <#instances> <#bytes> - # - 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) - # : 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) - # : 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 ": 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 : field; does nothing in JDK1.5.0 - s/^[1-9][0-9]*:'"${PATTERN_WS}${PATTERN_WS}"'*// - # strip 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 diff -r 4673729e145d -r 022799a053fe jdk/test/java/util/logging/LoggerWeakRefLeak.java --- a/jdk/test/java/util/logging/LoggerWeakRefLeak.java Tue Dec 23 12:40:06 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); - } -} diff -r 4673729e145d -r 022799a053fe jdk/test/java/util/logging/LoggerWeakRefLeak.sh --- a/jdk/test/java/util/logging/LoggerWeakRefLeak.sh Tue Dec 23 12:40:06 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> - # - # Output format for 'jmap -histo:live': - # - # : <#instances> <#bytes> - # - 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) - # : 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) - # : 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 ": 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 : field; does nothing in JDK1.5.0 - s/^[1-9][0-9]*:'"${PATTERN_WS}${PATTERN_WS}"'*// - # strip 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 diff -r 4673729e145d -r 022799a053fe jdk/test/java/util/logging/TestLoggerWeakRefLeak.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/logging/TestLoggerWeakRefLeak.java Wed Dec 24 20:23:31 2014 +0000 @@ -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 + } + } + +} diff -r 4673729e145d -r 022799a053fe jdk/test/sun/tools/common/CommonTests.sh --- a/jdk/test/sun/tools/common/CommonTests.sh Tue Dec 23 12:40:06 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