diff --git a/test/ProblemList.txt b/test/ProblemList.txt index 07b8db70b9a525ba6f1b4b1a1a09f5054a9e7719..47c05aaf7d87d748400f80a0500df8f83cc04123 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -134,10 +134,6 @@ java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all # 8021230 java/lang/ThreadLocal/ThreadLocalSupplierTest.java generic-all -# 8023201 -java/lang/instrument/RetransformBigClass.sh generic-all -java/lang/instrument/RedefineBigClass.sh generic-all - # 8026502 java/lang/invoke/MethodHandleConstants.java generic-all diff --git a/test/java/lang/instrument/NMTHelper.java b/test/java/lang/instrument/NMTHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..ad08fdb7708504351e9fe75e718f4689ecdb09f5 --- /dev/null +++ b/test/java/lang/instrument/NMTHelper.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013 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.regex.Matcher; +import java.util.regex.Pattern; +import sun.management.ManagementFactoryHelper; +import com.sun.management.DiagnosticCommandMBean; + +public class NMTHelper +{ + public static void baseline() { + executeDcmd("vmNativeMemory", "baseline"); + } + + // Total: reserved=3484685KB +293KB, committed=266629KB +293KB + private static Pattern totalLine = Pattern.compile("^Total: reserved=\\d+KB .*KB, committed=\\d+KB (.*)KB$"); + + public static long committedDiff() throws Exception { + String res = (String) executeDcmd("vmNativeMemory", "detail.diff"); + String[] lines = res.split("\n"); + for (String line : lines) { + Matcher matcher = totalLine.matcher(line); + if (matcher.matches()) { + String committed = matcher.group(1); + return Long.parseLong(committed); + } + } + throw new Exception("Could not find the Total line in the NMT output."); + } + + private static String executeDcmd(String cmd, String ... args) { + DiagnosticCommandMBean dcmd = ManagementFactoryHelper.getDiagnosticCommandMBean(); + Object[] dcmdArgs = {args}; + String[] signature = {String[].class.getName()}; + + try { + System.out.print("> " + cmd + " "); + for (String s : args) { + System.out.print(s + " "); + } + System.out.println(":"); + String result = (String) dcmd.invoke(cmd, dcmdArgs, signature); + System.out.println(result); + return result; + } catch(Exception ex) { + ex.printStackTrace(); + } + return null; + } +} diff --git a/test/java/lang/instrument/RedefineBigClass.sh b/test/java/lang/instrument/RedefineBigClass.sh index 145be056eb26485c7f3329c2bee6283e5d7541f8..82cfd4c9f18112666f0ddbc556669b1ba323f54b 100644 --- a/test/java/lang/instrument/RedefineBigClass.sh +++ b/test/java/lang/instrument/RedefineBigClass.sh @@ -58,11 +58,19 @@ fi JAVAC="${COMPILEJAVA}"/bin/javac JAVA="${TESTJAVA}"/bin/java +# Does this VM support the 'detail' level of NMT? +"${JAVA}" ${TESTVMOPTS} -XX:NativeMemoryTracking=detail -version +if [ "$?" = 0 ]; then + NMT=-XX:NativeMemoryTracking=detail +else + NMT=-XX:NativeMemoryTracking=summary +fi + "${JAVA}" ${TESTVMOPTS} \ - -XX:TraceRedefineClasses=3 \ + -XX:TraceRedefineClasses=3 ${NMT} \ -javaagent:RedefineBigClassAgent.jar=BigClass.class \ -classpath "${TESTCLASSES}" RedefineBigClassApp \ - > output.log 2>&1 + > output.log 2>&1 result=$? cat output.log diff --git a/test/java/lang/instrument/RedefineBigClassApp.java b/test/java/lang/instrument/RedefineBigClassApp.java index 81416303fc0efb07d32032b72e50c2fbf8e53925..40807d360b659286d033651b46f16812b7418f64 100644 --- a/test/java/lang/instrument/RedefineBigClassApp.java +++ b/test/java/lang/instrument/RedefineBigClassApp.java @@ -26,16 +26,23 @@ import java.io.*; public class RedefineBigClassApp { /** * Memory leak is assumed, if application consumes more than specified amount of memory during its execution. - * The number is given in Kb. + * The number is given in KB. */ - private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32Mb + private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32MB public static void main(String[] args) throws Exception { System.out.println("Creating instance of " + RedefineBigClassAgent.clz); RedefineBigClassAgent.clz.newInstance(); - long vMemBefore = getVMemSize(); + // Do a short warmup before creating the NMT baseline + try { + Thread.sleep(5 * 1000); + } catch (InterruptedException ie) { + } + + NMTHelper.baseline(); + int count = 0; while (!RedefineBigClassAgent.doneRedefining) { System.out.println("App loop count: " + ++count); @@ -46,39 +53,12 @@ public class RedefineBigClassApp { } System.out.println("App looped " + count + " times."); - long vMemAfter = getVMemSize(); - if (vMemBefore == 0 || vMemAfter == 0) { - System.err.println("WARNING: Cannot perform memory leak detection on this OS"); - } else { - long vMemDelta = vMemAfter - vMemBefore; - if (vMemDelta > MEM_LEAK_THRESHOLD) { - System.err.println("FAIL: Virtual memory usage increased by " + vMemDelta + "Kb " + - "(greater than " + MEM_LEAK_THRESHOLD + "Kb)"); - System.exit(1); - } - System.err.println("PASS: Virtual memory usage increased by " + vMemDelta + "Kb " + - "(not greater than " + MEM_LEAK_THRESHOLD + "Kb)"); + long committedDiff = NMTHelper.committedDiff(); + if (committedDiff > MEM_LEAK_THRESHOLD) { + throw new Exception("FAIL: Committed memory usage increased by " + committedDiff + "KB " + + "(greater than " + MEM_LEAK_THRESHOLD + "KB)"); } - System.exit(0); - } - - /** - * Return size of virtual memory allocated to the process in Kb. - * Linux specific. On other platforms and in case of any errors return 0. - */ - private static long getVMemSize() { - - // Refer to the Linux proc(5) man page for details about /proc/self/stat file - // - // In short, this file contains status information about the current process - // written in one line. The fields are separated with spaces. - // The 23rd field is defined as 'vsize %lu Virtual memory size in bytes' - - try (FileReader fileReader = new FileReader("/proc/self/stat"); - BufferedReader bufferedReader = new BufferedReader(fileReader)) { - String line = bufferedReader.readLine(); - return Long.parseLong(line.split(" ")[22]) / 1024; - } catch (Exception ex) {} - return 0; + System.err.println("PASS: Committed memory usage increased by " + committedDiff + "KB " + + "(not greater than " + MEM_LEAK_THRESHOLD + "KB)"); } } diff --git a/test/java/lang/instrument/RetransformBigClass.sh b/test/java/lang/instrument/RetransformBigClass.sh index dddde89c7853120586c670a9a6c5ace482fa80f4..d168395eb2ed974d57d8a2e62b54aecab14ef869 100644 --- a/test/java/lang/instrument/RetransformBigClass.sh +++ b/test/java/lang/instrument/RetransformBigClass.sh @@ -58,8 +58,16 @@ fi JAVAC="${COMPILEJAVA}"/bin/javac JAVA="${TESTJAVA}"/bin/java +# Does this VM support the 'detail' level of NMT? +"${JAVA}" ${TESTVMOPTS} -XX:NativeMemoryTracking=detail -version +if [ "$?" = 0 ]; then + NMT=-XX:NativeMemoryTracking=detail +else + NMT=-XX:NativeMemoryTracking=summary +fi + "${JAVA}" ${TESTVMOPTS} \ - -XX:TraceRedefineClasses=3 \ + -XX:TraceRedefineClasses=3 ${NMT} \ -javaagent:RetransformBigClassAgent.jar=BigClass.class \ -classpath "${TESTCLASSES}" RetransformBigClassApp \ > output.log 2>&1 diff --git a/test/java/lang/instrument/RetransformBigClassApp.java b/test/java/lang/instrument/RetransformBigClassApp.java index 3f777bbb20ea7cd1f3c27b7a0ad3bb69935fa8c0..01e305a1a26dd238b300f5e9582892f06b66895f 100644 --- a/test/java/lang/instrument/RetransformBigClassApp.java +++ b/test/java/lang/instrument/RetransformBigClassApp.java @@ -26,16 +26,23 @@ import java.io.*; public class RetransformBigClassApp { /** * Memory leak is assumed, if application consumes more than specified amount of memory during its execution. - * The number is given in Kb. + * The number is given in KB. */ - private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32Mb + private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32MB public static void main(String[] args) throws Exception { System.out.println("Creating instance of " + RetransformBigClassAgent.clz); RetransformBigClassAgent.clz.newInstance(); - long vMemBefore = getVMemSize(); + // Do a short warmup before creating the NMT baseline + try { + Thread.sleep(5 * 1000); + } catch (InterruptedException ie) { + } + + NMTHelper.baseline(); + int count = 0; while (!RetransformBigClassAgent.doneRetransforming) { System.out.println("App loop count: " + ++count); @@ -46,39 +53,12 @@ public class RetransformBigClassApp { } System.out.println("App looped " + count + " times."); - long vMemAfter = getVMemSize(); - if (vMemBefore == 0 || vMemAfter == 0) { - System.err.println("WARNING: Cannot perform memory leak detection on this OS"); - } else { - long vMemDelta = vMemAfter - vMemBefore; - if (vMemDelta > MEM_LEAK_THRESHOLD) { - System.err.println("FAIL: Virtual memory usage increased by " + vMemDelta + "Kb " + - "(greater than " + MEM_LEAK_THRESHOLD + "Kb)"); - System.exit(1); - } - System.err.println("PASS: Virtual memory usage increased by " + vMemDelta + "Kb " + - "(not greater than " + MEM_LEAK_THRESHOLD + "Kb)"); + long committedDiff = NMTHelper.committedDiff(); + if (committedDiff > MEM_LEAK_THRESHOLD) { + throw new Exception("FAIL: Committed memory usage increased by " + committedDiff + "KB " + + "(greater than " + MEM_LEAK_THRESHOLD + "KB)"); } - System.exit(0); - } - - /** - * Return size of virtual memory allocated to the process in Kb. - * Linux specific. On other platforms and in case of any errors return 0. - */ - private static long getVMemSize() { - - // Refer to the Linux proc(5) man page for details about /proc/self/stat file - // - // In short, this file contains status information about the current process - // written in one line. The fields are separated with spaces. - // The 23rd field is defined as 'vsize %lu Virtual memory size in bytes' - - try (FileReader fileReader = new FileReader("/proc/self/stat"); - BufferedReader bufferedReader = new BufferedReader(fileReader)) { - String line = bufferedReader.readLine(); - return Long.parseLong(line.split(" ")[22]) / 1024; - } catch (Exception ex) {} - return 0; + System.err.println("PASS: Committed memory usage increased by " + committedDiff + "KB " + + "(not greater than " + MEM_LEAK_THRESHOLD + "KB)"); } }