Tue, 16 Feb 2016 21:42:29 +0000
8072725: Provide more granular levels for GC verification
Summary: Add option VerifySubSet to selectively verify the memory sub-systems
Reviewed-by: kevinw, jmasa
1.1 --- a/src/share/vm/memory/universe.cpp Tue Feb 16 13:56:12 2016 +0000 1.2 +++ b/src/share/vm/memory/universe.cpp Tue Feb 16 21:42:29 2016 +0000 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -124,6 +124,7 @@ 1.11 objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL; 1.12 volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0; 1.13 bool Universe::_verify_in_progress = false; 1.14 +long Universe::verify_flags = Universe::Verify_All; 1.15 oop Universe::_null_ptr_exception_instance = NULL; 1.16 oop Universe::_arithmetic_exception_instance = NULL; 1.17 oop Universe::_virtual_machine_error_instance = NULL; 1.18 @@ -683,6 +684,9 @@ 1.19 MetaspaceShared::prepare_for_dumping(); 1.20 } 1.21 } 1.22 + if (strlen(VerifySubSet) > 0) { 1.23 + Universe::initialize_verify_flags(); 1.24 + } 1.25 1.26 return JNI_OK; 1.27 } 1.28 @@ -1361,6 +1365,53 @@ 1.29 st->print_cr("}"); 1.30 } 1.31 1.32 +void Universe::initialize_verify_flags() { 1.33 + verify_flags = 0; 1.34 + const char delimiter[] = " ,"; 1.35 + 1.36 + size_t length = strlen(VerifySubSet); 1.37 + char* subset_list = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal); 1.38 + strncpy(subset_list, VerifySubSet, length + 1); 1.39 + 1.40 + char* token = strtok(subset_list, delimiter); 1.41 + while (token != NULL) { 1.42 + if (strcmp(token, "threads") == 0) { 1.43 + verify_flags |= Verify_Threads; 1.44 + } else if (strcmp(token, "heap") == 0) { 1.45 + verify_flags |= Verify_Heap; 1.46 + } else if (strcmp(token, "symbol_table") == 0) { 1.47 + verify_flags |= Verify_SymbolTable; 1.48 + } else if (strcmp(token, "string_table") == 0) { 1.49 + verify_flags |= Verify_StringTable; 1.50 + } else if (strcmp(token, "codecache") == 0) { 1.51 + verify_flags |= Verify_CodeCache; 1.52 + } else if (strcmp(token, "dictionary") == 0) { 1.53 + verify_flags |= Verify_SystemDictionary; 1.54 + } else if (strcmp(token, "classloader_data_graph") == 0) { 1.55 + verify_flags |= Verify_ClassLoaderDataGraph; 1.56 + } else if (strcmp(token, "metaspace") == 0) { 1.57 + verify_flags |= Verify_MetaspaceAux; 1.58 + } else if (strcmp(token, "jni_handles") == 0) { 1.59 + verify_flags |= Verify_JNIHandles; 1.60 + } else if (strcmp(token, "c-heap") == 0) { 1.61 + verify_flags |= Verify_CHeap; 1.62 + } else if (strcmp(token, "codecache_oops") == 0) { 1.63 + verify_flags |= Verify_CodeCacheOops; 1.64 + } else { 1.65 + vm_exit_during_initialization(err_msg("VerifySubSet: \'%s\' memory sub-system is unknown, please correct it", token)); 1.66 + } 1.67 + token = strtok(NULL, delimiter); 1.68 + } 1.69 + FREE_C_HEAP_ARRAY(char, subset_list, mtInternal); 1.70 +} 1.71 + 1.72 +bool Universe::should_verify_subset(uint subset) { 1.73 + if (verify_flags & subset) { 1.74 + return true; 1.75 + } 1.76 + return false; 1.77 +} 1.78 + 1.79 void Universe::verify(VerifyOption option, const char* prefix, bool silent) { 1.80 // The use of _verify_in_progress is a temporary work around for 1.81 // 6320749. Don't bother with a creating a class to set and clear 1.82 @@ -1380,33 +1431,55 @@ 1.83 1.84 if (!silent) gclog_or_tty->print("%s", prefix); 1.85 if (!silent) gclog_or_tty->print("[Verifying "); 1.86 - if (!silent) gclog_or_tty->print("threads "); 1.87 - Threads::verify(); 1.88 - if (!silent) gclog_or_tty->print("heap "); 1.89 - heap()->verify(silent, option); 1.90 - if (!silent) gclog_or_tty->print("syms "); 1.91 - SymbolTable::verify(); 1.92 - if (!silent) gclog_or_tty->print("strs "); 1.93 - StringTable::verify(); 1.94 + if (should_verify_subset(Verify_Threads)) { 1.95 + if (!silent) gclog_or_tty->print("Threads "); 1.96 + Threads::verify(); 1.97 + } 1.98 + if (should_verify_subset(Verify_Heap)) { 1.99 + if (!silent) gclog_or_tty->print("Heap "); 1.100 + heap()->verify(silent, option); 1.101 + } 1.102 + if (should_verify_subset(Verify_SymbolTable)) { 1.103 + if (!silent) gclog_or_tty->print("SymbolTable "); 1.104 + SymbolTable::verify(); 1.105 + } 1.106 + if (should_verify_subset(Verify_StringTable)) { 1.107 + if (!silent) gclog_or_tty->print("StringTable "); 1.108 + StringTable::verify(); 1.109 + } 1.110 + if (should_verify_subset(Verify_CodeCache)) { 1.111 { 1.112 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 1.113 - if (!silent) gclog_or_tty->print("zone "); 1.114 + if (!silent) gclog_or_tty->print("CodeCache "); 1.115 CodeCache::verify(); 1.116 } 1.117 - if (!silent) gclog_or_tty->print("dict "); 1.118 - SystemDictionary::verify(); 1.119 + } 1.120 + if (should_verify_subset(Verify_SystemDictionary)) { 1.121 + if (!silent) gclog_or_tty->print("SystemDictionary "); 1.122 + SystemDictionary::verify(); 1.123 + } 1.124 #ifndef PRODUCT 1.125 - if (!silent) gclog_or_tty->print("cldg "); 1.126 - ClassLoaderDataGraph::verify(); 1.127 + if (should_verify_subset(Verify_ClassLoaderDataGraph)) { 1.128 + if (!silent) gclog_or_tty->print("ClassLoaderDataGraph "); 1.129 + ClassLoaderDataGraph::verify(); 1.130 + } 1.131 #endif 1.132 - if (!silent) gclog_or_tty->print("metaspace chunks "); 1.133 - MetaspaceAux::verify_free_chunks(); 1.134 - if (!silent) gclog_or_tty->print("hand "); 1.135 - JNIHandles::verify(); 1.136 - if (!silent) gclog_or_tty->print("C-heap "); 1.137 - os::check_heap(); 1.138 - if (!silent) gclog_or_tty->print("code cache "); 1.139 - CodeCache::verify_oops(); 1.140 + if (should_verify_subset(Verify_MetaspaceAux)) { 1.141 + if (!silent) gclog_or_tty->print("MetaspaceAux "); 1.142 + MetaspaceAux::verify_free_chunks(); 1.143 + } 1.144 + if (should_verify_subset(Verify_JNIHandles)) { 1.145 + if (!silent) gclog_or_tty->print("JNIHandles "); 1.146 + JNIHandles::verify(); 1.147 + } 1.148 + if (should_verify_subset(Verify_CHeap)) { 1.149 + if (!silent) gclog_or_tty->print("C-heap "); 1.150 + os::check_heap(); 1.151 + } 1.152 + if (should_verify_subset(Verify_CodeCacheOops)) { 1.153 + if (!silent) gclog_or_tty->print("CodeCache Oops "); 1.154 + CodeCache::verify_oops(); 1.155 + } 1.156 if (!silent) gclog_or_tty->print_cr("]"); 1.157 1.158 _verify_in_progress = false;
2.1 --- a/src/share/vm/memory/universe.hpp Tue Feb 16 13:56:12 2016 +0000 2.2 +++ b/src/share/vm/memory/universe.hpp Tue Feb 16 21:42:29 2016 +0000 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -247,6 +247,7 @@ 2.11 static int _verify_count; // number of verifies done 2.12 // True during call to verify(). Should only be set/cleared in verify(). 2.13 static bool _verify_in_progress; 2.14 + static long verify_flags; 2.15 2.16 static void compute_verify_oop_data(); 2.17 2.18 @@ -425,6 +426,22 @@ 2.19 static void init_self_patching_vtbl_list(void** list, int count); 2.20 2.21 // Debugging 2.22 + enum VERIFY_FLAGS { 2.23 + Verify_Threads = 1, 2.24 + Verify_Heap = 2, 2.25 + Verify_SymbolTable = 4, 2.26 + Verify_StringTable = 8, 2.27 + Verify_CodeCache = 16, 2.28 + Verify_SystemDictionary = 32, 2.29 + Verify_ClassLoaderDataGraph = 64, 2.30 + Verify_MetaspaceAux = 128, 2.31 + Verify_JNIHandles = 256, 2.32 + Verify_CHeap = 512, 2.33 + Verify_CodeCacheOops = 1024, 2.34 + Verify_All = -1 2.35 + }; 2.36 + static void initialize_verify_flags(); 2.37 + static bool should_verify_subset(uint subset); 2.38 static bool verify_in_progress() { return _verify_in_progress; } 2.39 static void verify(VerifyOption option, const char* prefix, bool silent = VerifySilently); 2.40 static void verify(const char* prefix, bool silent = VerifySilently) {
3.1 --- a/src/share/vm/runtime/globals.hpp Tue Feb 16 13:56:12 2016 +0000 3.2 +++ b/src/share/vm/runtime/globals.hpp Tue Feb 16 21:42:29 2016 +0000 3.3 @@ -2259,6 +2259,14 @@ 3.4 diagnostic(bool, VerifyDuringGC, false, \ 3.5 "Verify memory system during GC (between phases)") \ 3.6 \ 3.7 + diagnostic(ccstrlist, VerifySubSet, "", \ 3.8 + "Memory sub-systems to verify when Verify*GC flag(s) " \ 3.9 + "are enabled. One or more sub-systems can be specified " \ 3.10 + "in a comma separated string. Sub-systems are: " \ 3.11 + "threads, heap, symbol_table, string_table, codecache, " \ 3.12 + "dictionary, classloader_data_graph, metaspace, jni_handles, " \ 3.13 + "c-heap, codecache_oops") \ 3.14 + \ 3.15 diagnostic(bool, GCParallelVerificationEnabled, true, \ 3.16 "Enable parallel memory system verification") \ 3.17 \
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/gc/TestVerifySubSet.java Tue Feb 16 21:42:29 2016 +0000 4.3 @@ -0,0 +1,91 @@ 4.4 +/* 4.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +/* @test TestVerifySubSet.java 4.28 + * @key gc 4.29 + * @bug 8072725 4.30 + * @summary Test VerifySubSet option 4.31 + * @library /testlibrary 4.32 + */ 4.33 + 4.34 +import com.oracle.java.testlibrary.OutputAnalyzer; 4.35 +import com.oracle.java.testlibrary.ProcessTools; 4.36 +import java.util.ArrayList; 4.37 +import java.util.Collections; 4.38 + 4.39 +class RunSystemGC { 4.40 + public static void main(String args[]) throws Exception { 4.41 + System.gc(); 4.42 + } 4.43 +} 4.44 + 4.45 +public class TestVerifySubSet { 4.46 + private static String[] getTestJavaOpts() { 4.47 + String testVmOptsStr = System.getProperty("test.java.opts"); 4.48 + if (!testVmOptsStr.isEmpty()) { 4.49 + return testVmOptsStr.split(" "); 4.50 + } else { 4.51 + return new String[] {}; 4.52 + } 4.53 + } 4.54 + 4.55 + private static OutputAnalyzer runTest(String subset) throws Exception { 4.56 + ArrayList<String> vmOpts = new ArrayList(); 4.57 + 4.58 + Collections.addAll(vmOpts, getTestJavaOpts()); 4.59 + Collections.addAll(vmOpts, new String[] {"-XX:+UnlockDiagnosticVMOptions", 4.60 + "-XX:+VerifyBeforeGC", 4.61 + "-XX:+VerifyAfterGC", 4.62 + "-XX:VerifySubSet="+subset, 4.63 + RunSystemGC.class.getName()}); 4.64 + ProcessBuilder pb = 4.65 + ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); 4.66 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 4.67 + 4.68 + System.out.println("Output:\n" + output.getOutput()); 4.69 + return output; 4.70 + } 4.71 + 4.72 + public static void main(String args[]) throws Exception { 4.73 + 4.74 + OutputAnalyzer output; 4.75 + 4.76 + output = runTest("heap, threads, codecache, metaspace"); 4.77 + output.shouldContain("Heap"); 4.78 + output.shouldContain("Threads"); 4.79 + output.shouldContain("CodeCache"); 4.80 + output.shouldContain("MetaspaceAux"); 4.81 + output.shouldNotContain("SymbolTable"); 4.82 + output.shouldNotContain("StringTable"); 4.83 + output.shouldNotContain("SystemDictionary"); 4.84 + output.shouldNotContain("CodeCache Oops"); 4.85 + output.shouldHaveExitValue(0); 4.86 + 4.87 + output = runTest("hello, threads, codecache, metaspace"); 4.88 + output.shouldContain("memory sub-system is unknown, please correct it"); 4.89 + output.shouldNotContain("Threads"); 4.90 + output.shouldNotContain("CodeCache"); 4.91 + output.shouldNotContain("MetaspaceAux"); 4.92 + output.shouldHaveExitValue(1); 4.93 + } 4.94 +}