mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-26 14:50:34 +00:00
8175312: SA: clhsdb: Provide an improved heap summary for 'universe' for G1GC
Provide an improved heap summary for G1GC with parameters like 'capacity', 'used', 'free', etc with the 'universe' command, and introduce a new command 'g1regiondetails' to display the individual region details. Reviewed-by: sjohanss, minqi
This commit is contained in:
parent
3cbe6dfd8f
commit
9d036d6dd2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018, 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
|
||||
@ -73,8 +73,13 @@
|
||||
#define VM_INT_CONSTANTS_G1(declare_constant, declare_constant_with_value) \
|
||||
declare_constant(HeapRegionType::FreeTag) \
|
||||
declare_constant(HeapRegionType::YoungMask) \
|
||||
declare_constant(HeapRegionType::EdenTag) \
|
||||
declare_constant(HeapRegionType::SurvTag) \
|
||||
declare_constant(HeapRegionType::HumongousMask) \
|
||||
declare_constant(HeapRegionType::PinnedMask) \
|
||||
declare_constant(HeapRegionType::ArchiveMask) \
|
||||
declare_constant(HeapRegionType::StartsHumongousTag) \
|
||||
declare_constant(HeapRegionType::ContinuesHumongousTag) \
|
||||
declare_constant(HeapRegionType::OldMask)
|
||||
|
||||
|
||||
|
||||
@ -52,6 +52,8 @@ import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;
|
||||
import sun.jvm.hotspot.memory.SymbolTable;
|
||||
import sun.jvm.hotspot.memory.SystemDictionary;
|
||||
import sun.jvm.hotspot.memory.Universe;
|
||||
import sun.jvm.hotspot.gc.shared.CollectedHeap;
|
||||
import sun.jvm.hotspot.gc.g1.G1CollectedHeap;
|
||||
import sun.jvm.hotspot.oops.DefaultHeapVisitor;
|
||||
import sun.jvm.hotspot.oops.HeapVisitor;
|
||||
import sun.jvm.hotspot.oops.InstanceKlass;
|
||||
@ -1656,6 +1658,21 @@ public class CommandProcessor {
|
||||
}
|
||||
}
|
||||
},
|
||||
new Command("g1regiondetails", false) {
|
||||
public void doit(Tokens t) {
|
||||
if (t.countTokens() != 0) {
|
||||
usage();
|
||||
} else {
|
||||
CollectedHeap heap = VM.getVM().getUniverse().heap();
|
||||
if (!(heap instanceof G1CollectedHeap)) {
|
||||
out.println("This command is valid only for G1GC.");
|
||||
return;
|
||||
}
|
||||
out.println("Region Details:");
|
||||
((G1CollectedHeap)heap).printRegionDetails(out);
|
||||
}
|
||||
}
|
||||
},
|
||||
new Command("universe", false) {
|
||||
public void doit(Tokens t) {
|
||||
if (t.countTokens() != 0) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018, 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
|
||||
@ -33,6 +33,7 @@ import sun.jvm.hotspot.debugger.Address;
|
||||
import sun.jvm.hotspot.gc.shared.CollectedHeap;
|
||||
import sun.jvm.hotspot.gc.shared.CollectedHeapName;
|
||||
import sun.jvm.hotspot.gc.shared.SpaceClosure;
|
||||
import sun.jvm.hotspot.gc.shared.PrintRegionClosure;
|
||||
import sun.jvm.hotspot.memory.MemRegion;
|
||||
import sun.jvm.hotspot.runtime.VM;
|
||||
import sun.jvm.hotspot.runtime.VMObjectFactory;
|
||||
@ -40,6 +41,7 @@ import sun.jvm.hotspot.types.AddressField;
|
||||
import sun.jvm.hotspot.types.CIntegerField;
|
||||
import sun.jvm.hotspot.types.Type;
|
||||
import sun.jvm.hotspot.types.TypeDataBase;
|
||||
import sun.jvm.hotspot.tools.HeapSummary;
|
||||
|
||||
// Mirror class for G1CollectedHeap.
|
||||
|
||||
@ -133,6 +135,14 @@ public class G1CollectedHeap extends CollectedHeap {
|
||||
tty.print("garbage-first heap");
|
||||
tty.print(" [" + mr.start() + ", " + mr.end() + "]");
|
||||
tty.println(" region size " + (HeapRegion.grainBytes() / 1024) + "K");
|
||||
|
||||
HeapSummary sum = new HeapSummary();
|
||||
sum.printG1HeapSummary(this);
|
||||
}
|
||||
|
||||
public void printRegionDetails(PrintStream tty) {
|
||||
PrintRegionClosure prc = new PrintRegionClosure(tty);
|
||||
heapRegionIterate(prc);
|
||||
}
|
||||
|
||||
public G1CollectedHeap(Address addr) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018, 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
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
package sun.jvm.hotspot.gc.g1;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
@ -124,4 +125,9 @@ public class HeapRegion extends CompactibleSpace {
|
||||
public static long getPointerSize() {
|
||||
return pointerSize;
|
||||
}
|
||||
|
||||
public void printOn(PrintStream tty) {
|
||||
tty.print("Region: " + bottom() + "," + top() + "," + end());
|
||||
tty.println(":" + type.typeAnnotation());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, 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
|
||||
@ -40,8 +40,13 @@ public class HeapRegionType extends VMObject {
|
||||
|
||||
private static int freeTag;
|
||||
private static int youngMask;
|
||||
private static int edenTag;
|
||||
private static int survTag;
|
||||
private static int humongousMask;
|
||||
private static int startsHumongousTag;
|
||||
private static int continuesHumongousTag;
|
||||
private static int pinnedMask;
|
||||
private static int archiveMask;
|
||||
private static int oldMask;
|
||||
private static CIntegerField tagField;
|
||||
private int tag;
|
||||
@ -61,6 +66,11 @@ public class HeapRegionType extends VMObject {
|
||||
|
||||
freeTag = db.lookupIntConstant("HeapRegionType::FreeTag");
|
||||
youngMask = db.lookupIntConstant("HeapRegionType::YoungMask");
|
||||
edenTag = db.lookupIntConstant("HeapRegionType::EdenTag");
|
||||
survTag = db.lookupIntConstant("HeapRegionType::SurvTag");
|
||||
startsHumongousTag = db.lookupIntConstant("HeapRegionType::StartsHumongousTag");
|
||||
continuesHumongousTag = db.lookupIntConstant("HeapRegionType::ContinuesHumongousTag");
|
||||
archiveMask = db.lookupIntConstant("HeapRegionType::ArchiveMask");
|
||||
humongousMask = db.lookupIntConstant("HeapRegionType::HumongousMask");
|
||||
pinnedMask = db.lookupIntConstant("HeapRegionType::PinnedMask");
|
||||
oldMask = db.lookupIntConstant("HeapRegionType::OldMask");
|
||||
@ -70,6 +80,14 @@ public class HeapRegionType extends VMObject {
|
||||
return tagField.getValue(addr) == freeTag;
|
||||
}
|
||||
|
||||
public boolean isEden() {
|
||||
return tagField.getValue(addr) == edenTag;
|
||||
}
|
||||
|
||||
public boolean isSurvivor() {
|
||||
return tagField.getValue(addr) == survTag;
|
||||
}
|
||||
|
||||
public boolean isYoung() {
|
||||
return (tagField.getValue(addr) & youngMask) != 0;
|
||||
}
|
||||
@ -78,6 +96,18 @@ public class HeapRegionType extends VMObject {
|
||||
return (tagField.getValue(addr) & humongousMask) != 0;
|
||||
}
|
||||
|
||||
public boolean isStartsHumongous() {
|
||||
return tagField.getValue(addr) == startsHumongousTag;
|
||||
}
|
||||
|
||||
public boolean isContinuesHumongous() {
|
||||
return tagField.getValue(addr) == continuesHumongousTag;
|
||||
}
|
||||
|
||||
public boolean isArchive() {
|
||||
return (tagField.getValue(addr) & archiveMask) != 0;
|
||||
}
|
||||
|
||||
public boolean isPinned() {
|
||||
return (tagField.getValue(addr) & pinnedMask) != 0;
|
||||
}
|
||||
@ -89,4 +119,32 @@ public class HeapRegionType extends VMObject {
|
||||
public HeapRegionType(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public String typeAnnotation() {
|
||||
if (isFree()) {
|
||||
return "Free";
|
||||
}
|
||||
if (isEden()) {
|
||||
return "Eden";
|
||||
}
|
||||
if (isSurvivor()) {
|
||||
return "Survivor";
|
||||
}
|
||||
if (isStartsHumongous()) {
|
||||
return "StartsHumongous";
|
||||
}
|
||||
if (isContinuesHumongous()) {
|
||||
return "ContinuesHumongous";
|
||||
}
|
||||
if (isArchive()) {
|
||||
return "Archive";
|
||||
}
|
||||
if (isPinned()) {
|
||||
return "Pinned";
|
||||
}
|
||||
if (isOld()) {
|
||||
return "Old";
|
||||
}
|
||||
return "Unknown Region Type";
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.gc.shared;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import sun.jvm.hotspot.gc.g1.HeapRegion;
|
||||
|
||||
public class PrintRegionClosure implements SpaceClosure {
|
||||
private PrintStream tty;
|
||||
|
||||
public PrintRegionClosure(PrintStream tty) {
|
||||
this.tty = tty;
|
||||
}
|
||||
|
||||
public void doSpace(Space hr) {
|
||||
((HeapRegion)hr).printOn(tty);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2018, 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
|
||||
@ -111,22 +111,7 @@ public class HeapSummary extends Tool {
|
||||
}
|
||||
}
|
||||
} else if (heap instanceof G1CollectedHeap) {
|
||||
G1CollectedHeap g1h = (G1CollectedHeap) heap;
|
||||
G1MonitoringSupport g1mm = g1h.g1mm();
|
||||
long edenRegionNum = g1mm.edenRegionNum();
|
||||
long survivorRegionNum = g1mm.survivorRegionNum();
|
||||
HeapRegionSetBase oldSet = g1h.oldSet();
|
||||
HeapRegionSetBase humongousSet = g1h.humongousSet();
|
||||
long oldRegionNum = oldSet.length() + humongousSet.length();
|
||||
printG1Space("G1 Heap:", g1h.n_regions(),
|
||||
g1h.used(), g1h.capacity());
|
||||
System.out.println("G1 Young Generation:");
|
||||
printG1Space("Eden Space:", edenRegionNum,
|
||||
g1mm.edenUsed(), g1mm.edenCommitted());
|
||||
printG1Space("Survivor Space:", survivorRegionNum,
|
||||
g1mm.survivorUsed(), g1mm.survivorCommitted());
|
||||
printG1Space("G1 Old Generation:", oldRegionNum,
|
||||
g1mm.oldUsed(), g1mm.oldCommitted());
|
||||
printG1HeapSummary((G1CollectedHeap)heap);
|
||||
} else if (heap instanceof ParallelScavengeHeap) {
|
||||
ParallelScavengeHeap psh = (ParallelScavengeHeap) heap;
|
||||
PSYoungGen youngGen = psh.youngGen();
|
||||
@ -217,6 +202,24 @@ public class HeapSummary extends Tool {
|
||||
System.out.println(alignment + (double)space.used() * 100.0 / space.capacity() + "% used");
|
||||
}
|
||||
|
||||
public void printG1HeapSummary(G1CollectedHeap g1h) {
|
||||
G1MonitoringSupport g1mm = g1h.g1mm();
|
||||
long edenRegionNum = g1mm.edenRegionNum();
|
||||
long survivorRegionNum = g1mm.survivorRegionNum();
|
||||
HeapRegionSetBase oldSet = g1h.oldSet();
|
||||
HeapRegionSetBase humongousSet = g1h.humongousSet();
|
||||
long oldRegionNum = oldSet.length() + humongousSet.length();
|
||||
printG1Space("G1 Heap:", g1h.n_regions(),
|
||||
g1h.used(), g1h.capacity());
|
||||
System.out.println("G1 Young Generation:");
|
||||
printG1Space("Eden Space:", edenRegionNum,
|
||||
g1mm.edenUsed(), g1mm.edenCommitted());
|
||||
printG1Space("Survivor Space:", survivorRegionNum,
|
||||
g1mm.survivorUsed(), g1mm.survivorCommitted());
|
||||
printG1Space("G1 Old Generation:", oldRegionNum,
|
||||
g1mm.oldUsed(), g1mm.oldCommitted());
|
||||
}
|
||||
|
||||
private void printG1Space(String spaceName, long regionNum,
|
||||
long used, long capacity) {
|
||||
long free = capacity - used;
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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 java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8175312
|
||||
* @summary Test clhsdb 'g1regiondetails' and 'scanoops' commands for G1GC
|
||||
* @library /test/lib
|
||||
* @requires (vm.bits == "64" & os.maxMemory > 8g)
|
||||
* @run main/othervm/timeout=2400 ClhsdbRegionDetailsScanOopsForG1
|
||||
*/
|
||||
|
||||
public class ClhsdbRegionDetailsScanOopsForG1 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Starting ClhsdbRegionDetailsScanOopsForG1 test");
|
||||
|
||||
LingeredAppWithLargeStringArray theApp = null;
|
||||
try {
|
||||
ClhsdbLauncher test = new ClhsdbLauncher();
|
||||
List<String> vmArgs = new ArrayList<String>();
|
||||
vmArgs.add("-XX:+UseG1GC");
|
||||
vmArgs.add("-Xmx8g");
|
||||
vmArgs.add("-XX:G1HeapRegionSize=2m");
|
||||
|
||||
theApp = new LingeredAppWithLargeStringArray();
|
||||
LingeredApp.startApp(vmArgs, theApp);
|
||||
System.out.println("Started LingeredAppWithLargeStringArray with pid " + theApp.getPid());
|
||||
|
||||
List<String> cmds = List.of("g1regiondetails");
|
||||
Map<String, List<String>> expStrMap = new HashMap<>();
|
||||
Map<String, List<String>> unExpStrMap = new HashMap<>();
|
||||
|
||||
// Test that the various types of regions are listed with the
|
||||
// 'g1regiondetails' command
|
||||
expStrMap.put("g1regiondetails", List.of(
|
||||
"Region",
|
||||
"Eden",
|
||||
"Survivor",
|
||||
"StartsHumongous",
|
||||
"ContinuesHumongous",
|
||||
"Free"));
|
||||
unExpStrMap.put("g1regiondetails", List.of("Unknown Region Type"));
|
||||
String regionDetailsOutput = test.run(theApp.getPid(), cmds,
|
||||
expStrMap, unExpStrMap);
|
||||
if (regionDetailsOutput == null) {
|
||||
// Output could be null due to attach permission issues
|
||||
// and if we are skipping this.
|
||||
LingeredApp.stopApp(theApp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Test the output of 'scanoops' -- get the start and end addresses
|
||||
// from the StartsHumongous region. Ensure that it contains an
|
||||
// array of Strings.
|
||||
String[] snippets = regionDetailsOutput.split(":StartsHumongous");
|
||||
snippets = snippets[0].split("Region: ");
|
||||
String[] words = snippets[snippets.length - 1].split(",");
|
||||
// words[0] and words[1] represent the start and end addresses
|
||||
String cmd = "scanoops " + words[0] + " " + words[1];
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmd, List.of("[Ljava/lang/String"));
|
||||
test.run(theApp.getPid(), List.of(cmd), expStrMap, null);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Test ERROR " + ex, ex);
|
||||
} finally {
|
||||
LingeredApp.stopApp(theApp);
|
||||
}
|
||||
System.out.println("Test PASSED");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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 jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
public class LingeredAppWithLargeStringArray extends LingeredApp {
|
||||
public static void main(String args[]) {
|
||||
String[] hugeArray = new String[Integer.MAX_VALUE/8];
|
||||
String[] smallArray = {"Just", "for", "testing"};
|
||||
for (int i = 0; i < hugeArray.length/16; i++) {
|
||||
hugeArray[i] = new String(smallArray[i%3]);
|
||||
}
|
||||
LingeredApp.main(args);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, 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
|
||||
@ -87,6 +87,9 @@ public class TestUniverse {
|
||||
output.shouldContain("Heap Parameters");
|
||||
if (gc.contains("G1GC")) {
|
||||
output.shouldContain("garbage-first heap");
|
||||
output.shouldContain("region size");
|
||||
output.shouldContain("G1 Young Generation:");
|
||||
output.shouldContain("regions =");
|
||||
}
|
||||
if (gc.contains("UseConcMarkSweepGC")) {
|
||||
output.shouldContain("Gen 1: concurrent mark-sweep generation");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user