8273559: Shenandoah: Shenandoah should support multi-threaded heap dump
Reviewed-by: shade, rkennke, sgehwolf
This commit is contained in:
parent
f531b5c796
commit
8132bfd23f
src/hotspot/share/gc/shenandoah
shenandoahConcurrentGC.cppshenandoahHeap.cppshenandoahRootProcessor.cppshenandoahRootProcessor.hppshenandoahRootProcessor.inline.hpp
test/hotspot/jtreg/gc/shenandoah
@ -725,7 +725,7 @@ private:
|
||||
ShenandoahVMWeakRoots<true /*concurrent*/> _vm_roots;
|
||||
|
||||
// Roots related to concurrent class unloading
|
||||
ShenandoahClassLoaderDataRoots<true /* concurrent */, true /* single thread*/>
|
||||
ShenandoahClassLoaderDataRoots<true /* concurrent */>
|
||||
_cld_roots;
|
||||
ShenandoahConcurrentNMethodIterator _nmethod_itr;
|
||||
ShenandoahPhaseTimings::Phase _phase;
|
||||
@ -734,7 +734,7 @@ public:
|
||||
ShenandoahConcurrentWeakRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
|
||||
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Weak Roots"),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
|
||||
_nmethod_itr(ShenandoahCodeRoots::table()),
|
||||
_phase(phase) {
|
||||
if (ShenandoahHeap::heap()->unload_classes()) {
|
||||
@ -838,7 +838,8 @@ class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
|
||||
private:
|
||||
ShenandoahPhaseTimings::Phase _phase;
|
||||
ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /*single threaded*/> _cld_roots;
|
||||
ShenandoahClassLoaderDataRoots<true /*concurrent*/>
|
||||
_cld_roots;
|
||||
ShenandoahConcurrentNMethodIterator _nmethod_itr;
|
||||
|
||||
public:
|
||||
@ -846,7 +847,7 @@ public:
|
||||
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
|
||||
_phase(phase),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
|
||||
_nmethod_itr(ShenandoahCodeRoots::table()) {
|
||||
if (!ShenandoahHeap::heap()->unload_classes()) {
|
||||
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
@ -1317,7 +1317,8 @@ void ShenandoahHeap::scan_roots_for_iteration(ShenandoahScanObjectStack* oop_sta
|
||||
// This populates the work stack with initial objects
|
||||
// It is important to relinquish the associated locks before diving
|
||||
// into heap dumper
|
||||
ShenandoahHeapIterationRootScanner rp;
|
||||
uint n_workers = safepoint_workers() != NULL ? safepoint_workers()->active_workers() : 1;
|
||||
ShenandoahHeapIterationRootScanner rp(n_workers);
|
||||
rp.roots_do(oops);
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ ShenandoahSTWRootScanner::ShenandoahSTWRootScanner(ShenandoahPhaseTimings::Phase
|
||||
ShenandoahRootProcessor(phase),
|
||||
_thread_roots(phase, ShenandoahHeap::heap()->workers()->active_workers() > 1),
|
||||
_code_roots(phase),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers()),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
|
||||
_vm_roots(phase),
|
||||
_unload_classes(ShenandoahHeap::heap()->unload_classes()) {
|
||||
}
|
||||
@ -154,7 +154,7 @@ ShenandoahConcurrentRootScanner::ShenandoahConcurrentRootScanner(uint n_workers,
|
||||
ShenandoahRootProcessor(phase),
|
||||
_java_threads(phase, n_workers),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, n_workers),
|
||||
_cld_roots(phase, n_workers, false /*heap iteration*/),
|
||||
_codecache_snapshot(NULL),
|
||||
_phase(phase) {
|
||||
if (!ShenandoahHeap::heap()->unload_classes()) {
|
||||
@ -213,7 +213,7 @@ void ShenandoahConcurrentRootScanner::update_tlab_stats() {
|
||||
ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, n_workers),
|
||||
_cld_roots(phase, n_workers, false /*heap iteration*/),
|
||||
_thread_roots(phase, n_workers > 1),
|
||||
_weak_roots(phase),
|
||||
_code_roots(phase) {
|
||||
@ -222,7 +222,7 @@ ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimi
|
||||
ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, n_workers),
|
||||
_cld_roots(phase, n_workers, false /*heap iteration*/),
|
||||
_thread_roots(phase, n_workers > 1),
|
||||
_weak_roots(phase),
|
||||
_code_roots(phase) {
|
||||
@ -248,18 +248,18 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
|
||||
_thread_roots.oops_do(oops, NULL, worker_id);
|
||||
}
|
||||
|
||||
ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
|
||||
ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner(uint n_workers) :
|
||||
ShenandoahRootProcessor(ShenandoahPhaseTimings::heap_iteration_roots),
|
||||
_thread_roots(ShenandoahPhaseTimings::heap_iteration_roots, false /*is par*/),
|
||||
_vm_roots(ShenandoahPhaseTimings::heap_iteration_roots),
|
||||
_cld_roots(ShenandoahPhaseTimings::heap_iteration_roots, 1),
|
||||
_cld_roots(ShenandoahPhaseTimings::heap_iteration_roots, n_workers, true /*heap iteration*/),
|
||||
_weak_roots(ShenandoahPhaseTimings::heap_iteration_roots),
|
||||
_code_roots(ShenandoahPhaseTimings::heap_iteration_roots) {
|
||||
}
|
||||
|
||||
void ShenandoahHeapIterationRootScanner::roots_do(OopClosure* oops) {
|
||||
// Must use _claim_none to avoid interfering with concurrent CLDG iteration
|
||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
|
||||
// Must use _claim_other to avoid interfering with concurrent CLDG iteration
|
||||
CLDToOopClosure clds(oops, ClassLoaderData::_claim_other);
|
||||
MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations);
|
||||
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL);
|
||||
AlwaysTrueClosure always_true;
|
||||
|
@ -107,15 +107,13 @@ public:
|
||||
void code_blobs_do(CodeBlobClosure* blob_cl, uint worker_id);
|
||||
};
|
||||
|
||||
template <bool CONCURRENT, bool SINGLE_THREADED>
|
||||
template <bool CONCURRENT>
|
||||
class ShenandoahClassLoaderDataRoots {
|
||||
private:
|
||||
ShenandoahSharedSemaphore _semaphore;
|
||||
ShenandoahPhaseTimings::Phase _phase;
|
||||
|
||||
static uint worker_count(uint n_workers) {
|
||||
if (SINGLE_THREADED) return 1u;
|
||||
|
||||
// Limit concurrency a bit, otherwise it wastes resources when workers are tripping
|
||||
// over each other. This also leaves free workers to process other parts of the root
|
||||
// set, while admitted workers are busy with doing the CLDG walk.
|
||||
@ -123,7 +121,7 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers);
|
||||
ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers, bool heap_iteration);
|
||||
~ShenandoahClassLoaderDataRoots();
|
||||
|
||||
void always_strong_cld_do(CLDClosure* clds, uint worker_id);
|
||||
@ -164,7 +162,7 @@ class ShenandoahSTWRootScanner : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahCodeCacheRoots _code_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /* single_thread*/>
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/>
|
||||
_cld_roots;
|
||||
ShenandoahVMRoots<false /*concurrent*/>
|
||||
_vm_roots;
|
||||
@ -180,7 +178,7 @@ class ShenandoahConcurrentRootScanner : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahJavaThreadsIterator _java_threads;
|
||||
ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<true /*concurrent*/, false /* single-threaded*/>
|
||||
ShenandoahClassLoaderDataRoots<true /*concurrent*/>
|
||||
_cld_roots;
|
||||
ShenandoahNMethodTableSnapshot* _codecache_snapshot;
|
||||
ShenandoahPhaseTimings::Phase _phase;
|
||||
@ -201,13 +199,12 @@ class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
|
||||
_cld_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/> _cld_roots;
|
||||
ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots;
|
||||
ShenandoahCodeCacheRoots _code_roots;
|
||||
|
||||
public:
|
||||
ShenandoahHeapIterationRootScanner();
|
||||
ShenandoahHeapIterationRootScanner(uint n_workers);
|
||||
|
||||
void roots_do(OopClosure* cl);
|
||||
};
|
||||
@ -216,8 +213,7 @@ public:
|
||||
class ShenandoahRootUpdater : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
|
||||
_cld_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/> _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots;
|
||||
ShenandoahCodeCacheRoots _code_roots;
|
||||
@ -233,8 +229,7 @@ public:
|
||||
class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
|
||||
_cld_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/> _cld_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahVMWeakRoots<false /*concurrent*/> _weak_roots;
|
||||
ShenandoahCodeCacheRoots _code_roots;
|
||||
|
@ -75,14 +75,17 @@ void ShenandoahVMRoots<CONCURRENT>::oops_do(T* cl, uint worker_id) {
|
||||
_strong_roots.oops_do(cl);
|
||||
}
|
||||
|
||||
template <bool CONCURRENT, bool SINGLE_THREADED>
|
||||
ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers) :
|
||||
template <bool CONCURRENT>
|
||||
ShenandoahClassLoaderDataRoots<CONCURRENT>::ShenandoahClassLoaderDataRoots(ShenandoahPhaseTimings::Phase phase, uint n_workers, bool heap_iteration) :
|
||||
_semaphore(worker_count(n_workers)),
|
||||
_phase(phase) {
|
||||
if (!SINGLE_THREADED) {
|
||||
if (heap_iteration) {
|
||||
ClassLoaderDataGraph::clear_claimed_marks(ClassLoaderData::_claim_other);
|
||||
} else {
|
||||
ClassLoaderDataGraph::clear_claimed_marks();
|
||||
}
|
||||
if (CONCURRENT && !SINGLE_THREADED) {
|
||||
|
||||
if (CONCURRENT) {
|
||||
ClassLoaderDataGraph_lock->lock();
|
||||
}
|
||||
|
||||
@ -90,24 +93,19 @@ ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::ShenandoahClassLoad
|
||||
assert(CONCURRENT || SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
|
||||
}
|
||||
|
||||
template <bool CONCURRENT, bool SINGLE_THREADED>
|
||||
ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::~ShenandoahClassLoaderDataRoots() {
|
||||
if (CONCURRENT && !SINGLE_THREADED) {
|
||||
template <bool CONCURRENT>
|
||||
ShenandoahClassLoaderDataRoots<CONCURRENT>::~ShenandoahClassLoaderDataRoots() {
|
||||
if (CONCURRENT) {
|
||||
ClassLoaderDataGraph_lock->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
template <bool CONCURRENT, bool SINGLE_THREADED>
|
||||
void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do_impl(CldDo f, CLDClosure* clds, uint worker_id) {
|
||||
template <bool CONCURRENT>
|
||||
void ShenandoahClassLoaderDataRoots<CONCURRENT>::cld_do_impl(CldDo f, CLDClosure* clds, uint worker_id) {
|
||||
if (CONCURRENT) {
|
||||
if (_semaphore.try_acquire()) {
|
||||
ShenandoahWorkerTimingsTracker timer(_phase, ShenandoahPhaseTimings::CLDGRoots, worker_id);
|
||||
if (SINGLE_THREADED){
|
||||
MutexLocker ml(ClassLoaderDataGraph_lock, Mutex::_no_safepoint_check_flag);
|
||||
f(clds);
|
||||
} else {
|
||||
f(clds);
|
||||
}
|
||||
f(clds);
|
||||
_semaphore.claim_all();
|
||||
}
|
||||
} else {
|
||||
@ -116,13 +114,13 @@ void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do_impl(Cl
|
||||
}
|
||||
}
|
||||
|
||||
template <bool CONCURRENT, bool SINGLE_THREADED>
|
||||
void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::always_strong_cld_do(CLDClosure* clds, uint worker_id) {
|
||||
template <bool CONCURRENT>
|
||||
void ShenandoahClassLoaderDataRoots<CONCURRENT>::always_strong_cld_do(CLDClosure* clds, uint worker_id) {
|
||||
cld_do_impl(&ClassLoaderDataGraph::always_strong_cld_do, clds, worker_id);
|
||||
}
|
||||
|
||||
template <bool CONCURRENT, bool SINGLE_THREADED>
|
||||
void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do(CLDClosure* clds, uint worker_id) {
|
||||
template <bool CONCURRENT>
|
||||
void ShenandoahClassLoaderDataRoots<CONCURRENT>::cld_do(CLDClosure* clds, uint worker_id) {
|
||||
cld_do_impl(&ClassLoaderDataGraph::cld_do, clds, worker_id);
|
||||
}
|
||||
|
||||
|
156
test/hotspot/jtreg/gc/shenandoah/TestJcmdHeapDump.java
Normal file
156
test/hotspot/jtreg/gc/shenandoah/TestJcmdHeapDump.java
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Red Hat, Inc. 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 id=passive
|
||||
* @library /test/lib
|
||||
* @modules jdk.attach/com.sun.tools.attach
|
||||
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
|
||||
* -XX:+ShenandoahDegeneratedGC
|
||||
* TestJcmdHeapDump
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
|
||||
* -XX:-ShenandoahDegeneratedGC
|
||||
* TestJcmdHeapDump
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=aggressive
|
||||
* @library /test/lib
|
||||
* @modules jdk.attach/com.sun.tools.attach
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
|
||||
* -XX:+ShenandoahOOMDuringEvacALot
|
||||
* TestJcmdHeapDump
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
|
||||
* -XX:+ShenandoahAllocFailureALot
|
||||
* TestJcmdHeapDump
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
|
||||
* TestJcmdHeapDump
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=adaptive
|
||||
* @library /test/lib
|
||||
* @modules jdk.attach/com.sun.tools.attach
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
|
||||
* -Dtarget=10000
|
||||
* TestJcmdHeapDump
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=static
|
||||
* @library /test/lib
|
||||
* @modules jdk.attach/com.sun.tools.attach
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
|
||||
* TestJcmdHeapDump
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=compact
|
||||
* @library /test/lib
|
||||
* @modules jdk.attach/com.sun.tools.attach
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
|
||||
* TestJcmdHeapDump
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=iu-aggressive
|
||||
* @library /test/lib
|
||||
* @modules jdk.attach/com.sun.tools.attach
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGCHeuristics=aggressive
|
||||
* -XX:+ShenandoahOOMDuringEvacALot
|
||||
* TestJcmdHeapDump
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGCHeuristics=aggressive
|
||||
* -XX:+ShenandoahAllocFailureALot
|
||||
* TestJcmdHeapDump
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGCHeuristics=aggressive
|
||||
* TestJcmdHeapDump
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=iu
|
||||
* @requires vm.gc.Shenandoah
|
||||
* @library /test/lib
|
||||
* @modules jdk.attach/com.sun.tools.attach
|
||||
*
|
||||
* @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu
|
||||
* TestJcmdHeapDump
|
||||
*/
|
||||
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class TestJcmdHeapDump {
|
||||
public static void main(String[] args) {
|
||||
long pid = ProcessHandle.current().pid();
|
||||
JDKToolLauncher jcmd = JDKToolLauncher.createUsingTestJDK("jcmd");
|
||||
jcmd.addToolArg(String.valueOf(pid));
|
||||
jcmd.addToolArg("GC.heap_dump");
|
||||
String dumpFileName = "myheapdump" + String.valueOf(pid);
|
||||
jcmd.addToolArg(dumpFileName);
|
||||
|
||||
try {
|
||||
ProcessBuilder pb = new ProcessBuilder(jcmd.getCommand());
|
||||
Process jcmdProc = pb.start();
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(jcmdProc);
|
||||
jcmdProc.waitFor();
|
||||
output.shouldHaveExitValue(0);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Test failed: " + e);
|
||||
}
|
||||
|
||||
File f = new File(dumpFileName);
|
||||
if (f.exists()) {
|
||||
f.delete();
|
||||
} else {
|
||||
throw new RuntimeException("Dump file not created");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user