--- old/src/share/vm/memory/universe.cpp Wed Dec 23 09:14:25 2015 +++ new/src/share/vm/memory/universe.cpp Wed Dec 23 09:14:23 2015 @@ -1103,6 +1103,17 @@ } } +bool Universe::should_verify_subset(const char* subset) { + if (VerifySubSet == NULL || VerifySubSet[0] == '\0') { + // VerifySubSet is not specified, verify everything + return true; + } + if (strstr(VerifySubSet, subset)) { + return true; + } + return false; +} + void Universe::verify(VerifyOption option, const char* prefix) { // The use of _verify_in_progress is a temporary work around for // 6320749. Don't bother with a creating a class to set and clear @@ -1122,33 +1133,55 @@ FormatBuffer<> title("Verifying %s", prefix); GCTraceTime(Info, gc, verify) tm(title.buffer()); - log_debug(gc, verify)("Threads"); - Threads::verify(); - log_debug(gc, verify)("Heap"); - heap()->verify(option); - log_debug(gc, verify)("SymbolTable"); - SymbolTable::verify(); - log_debug(gc, verify)("StringTable"); - StringTable::verify(); + if (should_verify_subset("threads")) { + log_debug(gc, verify)("Threads"); + Threads::verify(); + } + if (should_verify_subset("heap")) { + log_debug(gc, verify)("Heap"); + heap()->verify(option); + } + if (should_verify_subset("symbol_table")) { + log_debug(gc, verify)("SymbolTable"); + SymbolTable::verify(); + } + if (should_verify_subset("string_table")) { + log_debug(gc, verify)("StringTable"); + StringTable::verify(); + } + if (should_verify_subset("codecache")) { { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); log_debug(gc, verify)("CodeCache"); CodeCache::verify(); } - log_debug(gc, verify)("SystemDictionary"); - SystemDictionary::verify(); + } + if (should_verify_subset("dictionary")) { + log_debug(gc, verify)("SystemDictionary"); + SystemDictionary::verify(); + } #ifndef PRODUCT - log_debug(gc, verify)("ClassLoaderDataGraph"); - ClassLoaderDataGraph::verify(); + if (should_verify_subset("classloader_data_graph")) { + log_debug(gc, verify)("ClassLoaderDataGraph"); + ClassLoaderDataGraph::verify(); + } #endif - log_debug(gc, verify)("MetaspaceAux"); - MetaspaceAux::verify_free_chunks(); - log_debug(gc, verify)("JNIHandles"); - JNIHandles::verify(); - log_debug(gc, verify)("C-heap"); - os::check_heap(); - log_debug(gc, verify)("CodeCache Oops"); - CodeCache::verify_oops(); + if (should_verify_subset("metaspace")) { + log_debug(gc, verify)("MetaspaceAux"); + MetaspaceAux::verify_free_chunks(); + } + if (should_verify_subset("jni_handles")) { + log_debug(gc, verify)("JNIHandles"); + JNIHandles::verify(); + } + if (should_verify_subset("c-heap")) { + log_debug(gc, verify)("C-heap"); + os::check_heap(); + } + if (should_verify_subset("codecache_oops")) { + log_debug(gc, verify)("CodeCache Oops"); + CodeCache::verify_oops(); + } _verify_in_progress = false; } --- old/src/share/vm/memory/universe.hpp Wed Dec 23 09:14:30 2015 +++ new/src/share/vm/memory/universe.hpp Wed Dec 23 09:14:29 2015 @@ -464,6 +464,7 @@ // Debugging static bool verify_in_progress() { return _verify_in_progress; } + static bool should_verify_subset(const char* subset); static void verify(VerifyOption option, const char* prefix); static void verify(const char* prefix) { verify(VerifyOption_Default, prefix); --- old/src/share/vm/runtime/globals.hpp Wed Dec 23 09:14:36 2015 +++ new/src/share/vm/runtime/globals.hpp Wed Dec 23 09:14:34 2015 @@ -2341,6 +2341,14 @@ diagnostic(bool, VerifyDuringGC, false, \ "Verify memory system during GC (between phases)") \ \ + diagnostic(ccstrlist, VerifySubSet, "", \ + "Memory sub-systems to verify when Verify*GC flag(s) \ + are enabled. One or more sub-systems can be specified \ + in a comma separated string. Sub-systems are: \ + threads, heap, symbol_table, string_table, codecache, \ + dictionary, classloader_data_graph, metaspace, jni_handles, \ + c-heap, codecache_oops") \ + \ diagnostic(bool, GCParallelVerificationEnabled, true, \ "Enable parallel memory system verification") \ \ --- /dev/null Wed Dec 23 09:14:43 2015 +++ new/test/gc/TestVerifySubSet.java Wed Dec 23 09:14:42 2015 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, 2015, 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 TestVerifySubSet.java + * @key gc + * @bug 8072725 + * @summary Test VerifySubSet option + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import java.util.ArrayList; +import java.util.Collections; + +class RunSystemGC { + public static void main(String args[]) throws Exception { + System.gc(); + } +} + +public class TestVerifySubSet { + private static String[] getTestJavaOpts() { + String testVmOptsStr = System.getProperty("test.java.opts"); + if (!testVmOptsStr.isEmpty()) { + return testVmOptsStr.split(" "); + } else { + return new String[] {}; + } + } + + private static OutputAnalyzer runTest(String subset) throws Exception { + ArrayList vmOpts = new ArrayList(); + + Collections.addAll(vmOpts, getTestJavaOpts()); + Collections.addAll(vmOpts, new String[] {"-XX:+UnlockDiagnosticVMOptions", + "-XX:+VerifyBeforeGC", + "-XX:+VerifyAfterGC", + "-Xlog:gc+verify=debug", + "-XX:VerifySubSet="+subset, + RunSystemGC.class.getName()}); + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + System.out.println("Output:\n" + output.getOutput()); + return output; + } + + + public static void main(String args[]) throws Exception { + + OutputAnalyzer output; + + output = runTest("heap, threads, codecache, metaspace"); + output.shouldContain("Heap"); + output.shouldContain("Threads"); + output.shouldContain("CodeCache"); + output.shouldContain("MetaspaceAux"); + + output.shouldNotContain("SymbolTable"); + output.shouldNotContain("StringTable"); + output.shouldNotContain("SystemDictionary"); + output.shouldNotContain("CodeCache Oops"); + + output.shouldHaveExitValue(0); + } +}