--- old/src/share/vm/gc_implementation/g1/concurrentMark.cpp 2014-07-10 17:13:20.294180618 +0200 +++ new/src/share/vm/gc_implementation/g1/concurrentMark.cpp 2014-07-10 17:13:20.178180622 +0200 @@ -2163,7 +2163,9 @@ g1h->increment_total_collections(); // Clean out dead classes and update Metaspace sizes. - ClassLoaderDataGraph::purge(); + if (G1ClassUnloadingEnabled) { + ClassLoaderDataGraph::purge(); + } MetaspaceGC::compute_new_size(); // We reclaimed old regions so we should calculate the sizes to make @@ -2591,24 +2593,27 @@ 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 (G1ClassUnloadingEnabled) { + 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); + } } } --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2014-07-10 17:13:20.774180601 +0200 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2014-07-10 17:13:20.654180605 +0200 @@ -4840,10 +4840,15 @@ 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 (G1ClassUnloadingEnabled) { + 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; @@ -4914,6 +4919,7 @@ double closure_app_time_sec = 0.0; bool during_im = _g1h->g1_policy()->during_initial_mark_pause(); + bool trace_metadata = during_im && G1ClassUnloadingEnabled; BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); @@ -4923,8 +4929,8 @@ &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. @@ -4936,7 +4942,7 @@ 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()); @@ -5953,6 +5959,7 @@ { StrongRootsScope srs(this); // InitialMark needs claim bits to keep track of the marked-through CLDs. + // FIXME: Needed? if (g1_policy()->during_initial_mark_pause()) { ClassLoaderDataGraph::clear_claimed_marks(); } --- old/src/share/vm/gc_implementation/g1/g1_globals.hpp 2014-07-10 17:13:21.274180584 +0200 +++ new/src/share/vm/gc_implementation/g1/g1_globals.hpp 2014-07-10 17:13:21.170180587 +0200 @@ -232,6 +232,9 @@ "If non-0 is the number of parallel rem set update threads, " \ "otherwise the value is determined ergonomically.") \ \ + product(bool, G1ClassUnloadingEnabled, true, \ + "Whether class unloading is enabled when using G1 GC") \ + \ develop(bool, G1VerifyCTCleanup, false, \ "Verify card table cleanup.") \ \ --- old/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp 2014-07-10 17:13:21.686180569 +0200 +++ new/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp 2014-07-10 17:13:21.582180573 +0200 @@ -94,26 +94,37 @@ inline bool HeapRegion::block_is_obj(const HeapWord* p) const { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - return !g1h->is_obj_dead(oop(p), this); + if (G1ClassUnloadingEnabled) { + 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(G1ClassUnloadingEnabled, + 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) { --- old/src/share/vm/gc_implementation/shared/vmGCOperations.cpp 2014-07-10 17:13:22.106180555 +0200 +++ new/src/share/vm/gc_implementation/shared/vmGCOperations.cpp 2014-07-10 17:13:21.998180559 +0200 @@ -195,6 +195,7 @@ 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) { @@ -202,7 +203,7 @@ return true; } - if (UseG1GC) { + if (UseG1GC && G1ClassUnloadingEnabled) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); g1h->g1_policy()->set_initiate_conc_mark_if_possible(); --- old/src/share/vm/memory/sharedHeap.cpp 2014-07-10 17:13:22.526180540 +0200 +++ new/src/share/vm/memory/sharedHeap.cpp 2014-07-10 17:13:22.418180544 +0200 @@ -159,9 +159,10 @@ 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. +#if INCLUDE_ALL_GCS + // 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 && G1ClassUnloadingEnabled && 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. @@ -169,9 +170,14 @@ _lock->notify_all(); } } +#endif } void SharedHeap::StrongRootsScope::wait_until_all_workers_done_with_threads(uint n_workers) { +#if INCLUDE_ALL_GCS + assert(UseG1GC, "Currently only used by G1"); + assert(G1ClassUnloadingEnabled, "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); @@ -179,6 +185,7 @@ _lock->wait(Mutex::_no_safepoint_check_flag, 0, false); } } +#endif } void SharedHeap::process_roots(bool activate_scope, --- old/test/TEST.groups 2014-07-10 17:13:22.954180525 +0200 +++ new/test/TEST.groups 2014-07-10 17:13:22.842180529 +0200 @@ -231,6 +231,7 @@ gc/arguments/TestMaxHeapSizeTools.java \ gc/arguments/TestMaxNewSize.java \ gc/arguments/TestUseCompressedOopsErgo.java \ + gc/class_unloading/TestG1ClassUnloadingEnabledHWM.java \ gc/g1/ \ gc/metaspace/G1AddMetaspaceDependency.java \ gc/metaspace/TestMetaspacePerfCounters.java \ @@ -271,7 +272,7 @@ gc/arguments/TestCMSHeapSizeFlags.java \ gc/arguments/TestMaxNewSize.java \ gc/arguments/TestUseCompressedOopsErgo.java \ - gc/class_unloading/TestCMSClassUnloadingDisabledHWM.java \ + gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java \ gc/concurrentMarkSweep/ \ gc/startup_warnings/TestCMS.java \ gc/startup_warnings/TestCMSIncrementalMode.java \ --- /dev/null 2014-07-07 17:25:41.434805685 +0200 +++ new/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java 2014-07-10 17:13:23.266180514 +0200 @@ -0,0 +1,59 @@ +/* + * 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. + */ + +import sun.hotspot.WhiteBox; + +class AllocateBeyondMetaspaceSize { + public static Object dummy; + + public static void main(String [] args) { + if (args.length != 2) { + throw new IllegalArgumentException("Usage: "); + } + + long metaspaceSize = Long.parseLong(args[0]); + long youngGenSize = Long.parseLong(args[1]); + + run(metaspaceSize, youngGenSize); + } + + private static void run(long metaspaceSize, long youngGenSize) { + WhiteBox wb = WhiteBox.getWhiteBox(); + + long allocationBeyondMetaspaceSize = metaspaceSize * 2; + long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize); + + triggerYoungGC(youngGenSize); + + wb.freeMetaspace(null, metaspace, metaspace); + } + + private static void triggerYoungGC(long youngGenSize) { + long approxAllocSize = 32 * 1024; + long numAllocations = 2 * youngGenSize / approxAllocSize; + + for (long i = 0; i < numAllocations; i++) { + dummy = new byte[(int)approxAllocSize]; + } + } +} --- old/test/gc/class_unloading/TestCMSClassUnloadingDisabledHWM.java 2014-07-10 17:13:23.846180494 +0200 +++ /dev/null 2014-07-07 17:25:41.434805685 +0200 @@ -1,105 +0,0 @@ -/* - * 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 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; - - public static void main(String [] args) { - if (args.length != 2) { - throw new IllegalArgumentException("Usage: "); - } - - long metaspaceSize = Long.parseLong(args[0]); - long youngGenSize = Long.parseLong(args[1]); - - run(metaspaceSize, youngGenSize); - } - - private static void run(long metaspaceSize, long youngGenSize) { - WhiteBox wb = WhiteBox.getWhiteBox(); - - long allocationBeyondMetaspaceSize = metaspaceSize * 2; - long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize); - - triggerYoungGC(youngGenSize); - - wb.freeMetaspace(null, metaspace, metaspace); - } - - private static void triggerYoungGC(long youngGenSize) { - long approxAllocSize = 32 * 1024; - long numAllocations = 2 * youngGenSize / approxAllocSize; - - for (long i = 0; i < numAllocations; i++) { - dummy = new byte[(int)approxAllocSize]; - } - } -} --- /dev/null 2014-07-07 17:25:41.434805685 +0200 +++ new/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java 2014-07-10 17:13:23.638180501 +0200 @@ -0,0 +1,90 @@ +/* + * 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(); + } +} + --- /dev/null 2014-07-07 17:25:41.434805685 +0200 +++ new/test/gc/class_unloading/TestG1ClassUnloadingEnabledHWM.java 2014-07-10 17:13:24.162180483 +0200 @@ -0,0 +1,90 @@ +/* + * 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 TestG1ClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver TestG1ClassUnloadingEnabledHWM + * @summary Test that -XX:-G1ClassUnloadingEnabled 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 TestG1ClassUnloadingEnabledHWM { + 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 ? "+" : "-") + "G1ClassUnloadingEnabled", + "-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:-G1ClassUnloadingEnabled 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:+G1ClassUnloadingEnabled 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(); + } +} +