提交 bca48990 编写于 作者: S stefank

8048269: Add flag to turn off class unloading after G1 concurrent mark

Summary: Added -XX:+/-ClassUnloadingWithConcurrentMark
Reviewed-by: jmasa, brutisso, mgerdin
上级 a506f1d6
......@@ -2157,7 +2157,9 @@ void ConcurrentMark::cleanup() {
g1h->increment_total_collections();
// Clean out dead classes and update Metaspace sizes.
ClassLoaderDataGraph::purge();
if (ClassUnloadingWithConcurrentMark) {
ClassLoaderDataGraph::purge();
}
MetaspaceGC::compute_new_size();
// We reclaimed old regions so we should calculate the sizes to make
......@@ -2585,24 +2587,27 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
assert(_markStack.isEmpty(), "Marking should have completed");
// Unload Klasses, String, Symbols, Code Cache, etc.
{
G1RemarkGCTraceTime trace("Unloading", G1Log::finer());
G1RemarkGCTraceTime trace("Unloading", G1Log::finer());
bool purged_classes;
if (ClassUnloadingWithConcurrentMark) {
bool purged_classes;
{
G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest());
purged_classes = SystemDictionary::do_unloading(&g1_is_alive);
}
{
G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest());
purged_classes = SystemDictionary::do_unloading(&g1_is_alive);
}
{
G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest());
weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
}
{
G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest());
weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
}
}
if (G1StringDedup::is_enabled()) {
G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest());
G1StringDedup::unlink(&g1_is_alive);
if (G1StringDedup::is_enabled()) {
G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest());
G1StringDedup::unlink(&g1_is_alive);
}
}
}
......
......@@ -4860,10 +4860,15 @@ public:
if (_g1h->g1_policy()->during_initial_mark_pause()) {
// We also need to mark copied objects.
strong_root_cl = &scan_mark_root_cl;
weak_root_cl = &scan_mark_weak_root_cl;
strong_cld_cl = &scan_mark_cld_cl;
weak_cld_cl = &scan_mark_weak_cld_cl;
strong_code_cl = &scan_mark_code_cl;
if (ClassUnloadingWithConcurrentMark) {
weak_root_cl = &scan_mark_weak_root_cl;
weak_cld_cl = &scan_mark_weak_cld_cl;
} else {
weak_root_cl = &scan_mark_root_cl;
weak_cld_cl = &scan_mark_cld_cl;
}
} else {
strong_root_cl = &scan_only_root_cl;
weak_root_cl = &scan_only_root_cl;
......@@ -4934,6 +4939,7 @@ g1_process_roots(OopClosure* scan_non_heap_roots,
double closure_app_time_sec = 0.0;
bool during_im = _g1h->g1_policy()->during_initial_mark_pause();
bool trace_metadata = during_im && ClassUnloadingWithConcurrentMark;
BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
......@@ -4943,8 +4949,8 @@ g1_process_roots(OopClosure* scan_non_heap_roots,
&buf_scan_non_heap_roots,
&buf_scan_non_heap_weak_roots,
scan_strong_clds,
// Initial Mark handles the weak CLDs separately.
(during_im ? NULL : scan_weak_clds),
// Unloading Initial Marks handle the weak CLDs separately.
(trace_metadata ? NULL : scan_weak_clds),
scan_strong_code);
// Now the CM ref_processor roots.
......@@ -4956,7 +4962,7 @@ g1_process_roots(OopClosure* scan_non_heap_roots,
ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
}
if (during_im) {
if (trace_metadata) {
// Barrier to make sure all workers passed
// the strong CLD and strong nmethods phases.
active_strong_roots_scope()->wait_until_all_workers_done_with_threads(n_par_threads());
......
......@@ -94,26 +94,37 @@ G1OffsetTableContigSpace::block_start_const(const void* p) const {
inline bool
HeapRegion::block_is_obj(const HeapWord* p) const {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
return !g1h->is_obj_dead(oop(p), this);
if (ClassUnloadingWithConcurrentMark) {
return !g1h->is_obj_dead(oop(p), this);
}
return p < top();
}
inline size_t
HeapRegion::block_size(const HeapWord *addr) const {
if (addr == top()) {
return pointer_delta(end(), addr);
}
if (block_is_obj(addr)) {
return oop(addr)->size();
}
assert(ClassUnloadingWithConcurrentMark,
err_msg("All blocks should be objects if G1 Class Unloading isn't used. "
"HR: ["PTR_FORMAT", "PTR_FORMAT", "PTR_FORMAT") "
"addr: " PTR_FORMAT,
p2i(bottom()), p2i(top()), p2i(end()), p2i(addr)));
// Old regions' dead objects may have dead classes
// We need to find the next live object in some other
// manner than getting the oop size
G1CollectedHeap* g1h = G1CollectedHeap::heap();
if (g1h->is_obj_dead(oop(addr), this)) {
HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()->
getNextMarkedWordAddress(addr, prev_top_at_mark_start());
assert(next > addr, "must get the next live object");
HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()->
getNextMarkedWordAddress(addr, prev_top_at_mark_start());
return pointer_delta(next, addr);
} else if (addr == top()) {
return pointer_delta(end(), addr);
}
return oop(addr)->size();
assert(next > addr, "must get the next live object");
return pointer_delta(next, addr);
}
inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t word_size) {
......
......@@ -209,6 +209,7 @@ void VM_GenCollectFull::doit() {
gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
}
// Returns true iff concurrent GCs unloads metadata.
bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() {
#if INCLUDE_ALL_GCS
if (UseConcMarkSweepGC && CMSClassUnloadingEnabled) {
......@@ -216,7 +217,7 @@ bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() {
return true;
}
if (UseG1GC) {
if (UseG1GC && ClassUnloadingWithConcurrentMark) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
g1h->g1_policy()->set_initiate_conc_mark_if_possible();
......
......@@ -159,9 +159,9 @@ SharedHeap::StrongRootsScope::~StrongRootsScope() {
Monitor* SharedHeap::StrongRootsScope::_lock = new Monitor(Mutex::leaf, "StrongRootsScope lock", false);
void SharedHeap::StrongRootsScope::mark_worker_done_with_threads(uint n_workers) {
// The Thread work barrier is only needed by G1.
// The Thread work barrier is only needed by G1 Class Unloading.
// No need to use the barrier if this is single-threaded code.
if (UseG1GC && n_workers > 0) {
if (UseG1GC && ClassUnloadingWithConcurrentMark && n_workers > 0) {
uint new_value = (uint)Atomic::add(1, &_n_workers_done_with_threads);
if (new_value == n_workers) {
// This thread is last. Notify the others.
......@@ -172,6 +172,9 @@ void SharedHeap::StrongRootsScope::mark_worker_done_with_threads(uint n_workers)
}
void SharedHeap::StrongRootsScope::wait_until_all_workers_done_with_threads(uint n_workers) {
assert(UseG1GC, "Currently only used by G1");
assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
// No need to use the barrier if this is single-threaded code.
if (n_workers > 0 && (uint)_n_workers_done_with_threads != n_workers) {
MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
......
......@@ -1064,6 +1064,9 @@ class CommandLineFlags {
product(bool, ClassUnloading, true, \
"Do unloading of classes") \
\
product(bool, ClassUnloadingWithConcurrentMark, true, \
"Do unloading of classes with a concurrent marking cycle") \
\
develop(bool, DisableStartThread, false, \
"Disable starting of additional Java threads " \
"(for debugging only)") \
......
......@@ -170,6 +170,7 @@ compact1 = \
needs_full_vm_compact1 = \
runtime/NMT \
gc/class_unloading/TestCMSClassUnloadingDisabledHWM.java \
gc/class_unloading/TestG1ClassUnloadingHWM.java \
gc/g1/TestRegionAlignment.java \
gc/g1/TestShrinkToOneRegion.java \
gc/metaspace/G1AddMetaspaceDependency.java \
......
......@@ -21,54 +21,8 @@
* questions.
*/
/*
* @test
* @key gc
* @bug 8049831
* @library /testlibrary /testlibrary/whitebox
* @build TestCMSClassUnloadingDisabledHWM
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run driver TestCMSClassUnloadingDisabledHWM
* @summary Test that -XX:-CMSClassUnloadingEnabled will trigger a Full GC when more than MetaspaceSize metadata is allocated.
*/
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
import sun.hotspot.WhiteBox;
import java.util.ArrayList;
import java.util.Arrays;
public class TestCMSClassUnloadingDisabledHWM {
private static OutputAnalyzer run(long metaspaceSize, long youngGenSize) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-Xbootclasspath/a:.",
"-XX:+WhiteBoxAPI",
"-XX:MetaspaceSize=" + metaspaceSize,
"-Xmn" + youngGenSize,
"-XX:+UseConcMarkSweepGC",
"-XX:-CMSClassUnloadingEnabled",
"-XX:+PrintHeapAtGC",
"-XX:+PrintGCDetails",
"AllocateBeyondMetaspaceSize",
"" + metaspaceSize,
"" + youngGenSize);
return new OutputAnalyzer(pb.start());
}
public static void main(String args[]) throws Exception {
long metaspaceSize = 32 * 1024 * 1024;
long youngGenSize = 32 * 1024 * 1024;
OutputAnalyzer out = run(metaspaceSize, youngGenSize);
// -XX:-CMSClassUnloadingEnabled is used, so we expect a full GC instead of a concurrent cycle.
out.shouldMatch(".*Full GC.*");
out.shouldNotMatch(".*CMS Initial Mark.*");
}
}
class AllocateBeyondMetaspaceSize {
public static Object dummy;
......
/*
* Copyright (c) 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.
*/
/*
* @test
* @key gc
* @bug 8049831
* @library /testlibrary /testlibrary/whitebox
* @build TestCMSClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run driver TestCMSClassUnloadingEnabledHWM
* @summary Test that -XX:-CMSClassUnloadingEnabled will trigger a Full GC when more than MetaspaceSize metadata is allocated.
*/
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
import java.util.ArrayList;
import java.util.Arrays;
public class TestCMSClassUnloadingEnabledHWM {
private static long MetaspaceSize = 32 * 1024 * 1024;
private static long YoungGenSize = 32 * 1024 * 1024;
private static OutputAnalyzer run(boolean enableUnloading) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-Xbootclasspath/a:.",
"-XX:+WhiteBoxAPI",
"-XX:MetaspaceSize=" + MetaspaceSize,
"-Xmn" + YoungGenSize,
"-XX:+UseConcMarkSweepGC",
"-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled",
"-XX:+PrintHeapAtGC",
"-XX:+PrintGCDetails",
"AllocateBeyondMetaspaceSize",
"" + MetaspaceSize,
"" + YoungGenSize);
return new OutputAnalyzer(pb.start());
}
public static OutputAnalyzer runWithCMSClassUnloading() throws Exception {
return run(true);
}
public static OutputAnalyzer runWithoutCMSClassUnloading() throws Exception {
return run(false);
}
public static void testWithoutCMSClassUnloading() throws Exception {
// -XX:-CMSClassUnloadingEnabled is used, so we expect a full GC instead of a concurrent cycle.
OutputAnalyzer out = runWithoutCMSClassUnloading();
out.shouldMatch(".*Full GC.*");
out.shouldNotMatch(".*CMS Initial Mark.*");
}
public static void testWithCMSClassUnloading() throws Exception {
// -XX:+CMSClassUnloadingEnabled is used, so we expect a concurrent cycle instead of a full GC.
OutputAnalyzer out = runWithCMSClassUnloading();
out.shouldMatch(".*CMS Initial Mark.*");
out.shouldNotMatch(".*Full GC.*");
}
public static void main(String args[]) throws Exception {
testWithCMSClassUnloading();
testWithoutCMSClassUnloading();
}
}
/*
* Copyright (c) 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.
*/
/*
* @test
* @key gc
* @bug 8049831
* @library /testlibrary /testlibrary/whitebox
* @build TestG1ClassUnloadingHWM AllocateBeyondMetaspaceSize
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run driver TestG1ClassUnloadingHWM
* @summary Test that -XX:-ClassUnloadingWithConcurrentMark will trigger a Full GC when more than MetaspaceSize metadata is allocated.
*/
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
import java.util.ArrayList;
import java.util.Arrays;
public class TestG1ClassUnloadingHWM {
private static long MetaspaceSize = 32 * 1024 * 1024;
private static long YoungGenSize = 32 * 1024 * 1024;
private static OutputAnalyzer run(boolean enableUnloading) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-Xbootclasspath/a:.",
"-XX:+WhiteBoxAPI",
"-XX:MetaspaceSize=" + MetaspaceSize,
"-Xmn" + YoungGenSize,
"-XX:+UseG1GC",
"-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark",
"-XX:+PrintHeapAtGC",
"-XX:+PrintGCDetails",
"AllocateBeyondMetaspaceSize",
"" + MetaspaceSize,
"" + YoungGenSize);
return new OutputAnalyzer(pb.start());
}
public static OutputAnalyzer runWithG1ClassUnloading() throws Exception {
return run(true);
}
public static OutputAnalyzer runWithoutG1ClassUnloading() throws Exception {
return run(false);
}
public static void testWithoutG1ClassUnloading() throws Exception {
// -XX:-ClassUnloadingWithConcurrentMark is used, so we expect a full GC instead of a concurrent cycle.
OutputAnalyzer out = runWithoutG1ClassUnloading();
out.shouldMatch(".*Full GC.*");
out.shouldNotMatch(".*initial-mark.*");
}
public static void testWithG1ClassUnloading() throws Exception {
// -XX:+ClassUnloadingWithConcurrentMark is used, so we expect a concurrent cycle instead of a full GC.
OutputAnalyzer out = runWithG1ClassUnloading();
out.shouldMatch(".*initial-mark.*");
out.shouldNotMatch(".*Full GC.*");
}
public static void main(String args[]) throws Exception {
testWithG1ClassUnloading();
testWithoutG1ClassUnloading();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册