Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java
41161 views
/*1* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.utilities;2526import java.io.*;27import sun.jvm.hotspot.debugger.*;28import sun.jvm.hotspot.gc.shared.OopStorage;29import sun.jvm.hotspot.memory.*;30import sun.jvm.hotspot.oops.*;31import sun.jvm.hotspot.runtime.*;3233/**34* This is abstract base class for heap graph writers. This class does35* not assume any file format for the heap graph. It hides heap36* iteration, object (fields) iteration mechanism from derived37* classes. This class does not even accept OutputStream etc. so that38* derived class can construct specific writer/filter from input39* stream.40*/4142public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {43// the function iterates heap and calls Oop type specific writers44protected void write() throws IOException {45javaLangClass = "java/lang/Class";46javaLangString = "java/lang/String";47javaLangThread = "java/lang/Thread";48ObjectHeap heap = VM.getVM().getObjectHeap();49try {50heap.iterate(new DefaultHeapVisitor() {51public void prologue(long usedSize) {52try {53writeHeapHeader();54} catch (IOException exp) {55throw new RuntimeException(exp);56}57}5859public boolean doObj(Oop oop) {60try {61writeHeapRecordPrologue();62if (oop instanceof TypeArray) {63writePrimitiveArray((TypeArray)oop);64} else if (oop instanceof ObjArray) {65Klass klass = oop.getKlass();66ObjArrayKlass oak = (ObjArrayKlass) klass;67Klass bottomType = oak.getBottomKlass();68if (bottomType instanceof InstanceKlass ||69bottomType instanceof TypeArrayKlass) {70writeObjectArray((ObjArray)oop);71} else {72writeInternalObject(oop);73}74} else if (oop instanceof Instance) {75Instance instance = (Instance) oop;76Klass klass = instance.getKlass();77Symbol name = klass.getName();78if (name.equals(javaLangString)) {79writeString(instance);80} else if (name.equals(javaLangClass)) {81writeClass(instance);82} else if (name.equals(javaLangThread)) {83writeThread(instance);84} else {85klass = klass.getSuper();86while (klass != null) {87name = klass.getName();88if (name.equals(javaLangThread)) {89writeThread(instance);90return false;91}92klass = klass.getSuper();93}94writeInstance(instance);95}96} else {97// not-a-Java-visible oop98writeInternalObject(oop);99}100writeHeapRecordEpilogue();101} catch (IOException exp) {102throw new RuntimeException(exp);103}104return false;105}106107public void epilogue() {108try {109writeHeapFooter();110} catch (IOException exp) {111throw new RuntimeException(exp);112}113}114});115116writeHeapRecordPrologue();117118// write JavaThreads119writeJavaThreads();120121// write JNI global handles122writeGlobalJNIHandles();123124} catch (RuntimeException re) {125handleRuntimeException(re);126}127}128129protected void writeJavaThreads() throws IOException {130Threads threads = VM.getVM().getThreads();131for (int i = 0; i < threads.getNumberOfThreads(); i++) {132JavaThread jt = threads.getJavaThreadAt(i);133if (jt.getThreadObj() != null) {134// Note that the thread serial number range is 1-to-N135writeJavaThread(jt, i + 1);136}137}138}139140protected void writeJavaThread(JavaThread jt, int index)141throws IOException {142}143144protected void writeGlobalJNIHandles() throws IOException {145JNIHandles handles = VM.getVM().getJNIHandles();146OopStorage blk = handles.globalHandles();147if (blk != null) {148try {149blk.oopsDo(new AddressVisitor() {150public void visitAddress(Address handleAddr) {151try {152if (handleAddr != null) {153writeGlobalJNIHandle(handleAddr);154}155} catch (IOException exp) {156throw new RuntimeException(exp);157}158}159public void visitCompOopAddress(Address handleAddr) {160throw new RuntimeException("Should not reach here. JNIHandles are not compressed");161}162});163} catch (RuntimeException re) {164handleRuntimeException(re);165}166}167}168169protected void writeGlobalJNIHandle(Address handleAddr) throws IOException {170}171172protected void writeHeapHeader() throws IOException {173}174175// write non-Java-visible (hotspot internal) object176protected void writeInternalObject(Oop oop) throws IOException {177}178179// write Java primitive array180protected void writePrimitiveArray(TypeArray array) throws IOException {181writeObject(array);182}183184// write Java object array185protected void writeObjectArray(ObjArray array) throws IOException {186writeObject(array);187}188189protected void writeInstance(Instance instance) throws IOException {190writeObject(instance);191}192193protected void writeString(Instance instance) throws IOException {194writeInstance(instance);195}196197protected void writeClass(Instance instance) throws IOException {198writeInstance(instance);199}200201protected void writeThread(Instance instance) throws IOException {202writeInstance(instance);203}204205protected void writeObject(Oop oop) throws IOException {206writeObjectHeader(oop);207writeObjectFields(oop);208writeObjectFooter(oop);209}210211protected void writeObjectHeader(Oop oop) throws IOException {212}213214// write instance fields of given object215protected void writeObjectFields(final Oop oop) throws IOException {216try {217oop.iterate(new DefaultOopVisitor() {218public void doOop(OopField field, boolean isVMField) {219try {220writeReferenceField(oop, field);221} catch (IOException exp) {222throw new RuntimeException(exp);223}224}225226public void doByte(ByteField field, boolean isVMField) {227try {228writeByteField(oop, field);229} catch (IOException exp) {230throw new RuntimeException(exp);231}232}233234public void doChar(CharField field, boolean isVMField) {235try {236writeCharField(oop, field);237} catch (IOException exp) {238throw new RuntimeException(exp);239}240}241242public void doBoolean(BooleanField field, boolean vField) {243try {244writeBooleanField(oop, field);245} catch (IOException exp) {246throw new RuntimeException(exp);247}248}249250public void doShort(ShortField field, boolean isVMField) {251try {252writeShortField(oop, field);253} catch (IOException exp) {254throw new RuntimeException(exp);255}256}257258public void doInt(IntField field, boolean isVMField) {259try {260writeIntField(oop, field);261} catch (IOException exp) {262throw new RuntimeException(exp);263}264}265266public void doLong(LongField field, boolean isVMField) {267try {268writeLongField(oop, field);269} catch (IOException exp) {270throw new RuntimeException(exp);271}272}273274public void doFloat(FloatField field, boolean isVMField) {275try {276writeFloatField(oop, field);277} catch (IOException exp) {278throw new RuntimeException(exp);279}280}281282public void doDouble(DoubleField field, boolean vField) {283try {284writeDoubleField(oop, field);285} catch (IOException exp) {286throw new RuntimeException(exp);287}288}289}, false);290} catch (RuntimeException re) {291handleRuntimeException(re);292}293}294295// write instance fields of given object296protected void writeObjectFields(final InstanceKlass oop) throws IOException {297try {298oop.iterateStaticFields(new DefaultOopVisitor() {299public void doOop(OopField field, boolean isVMField) {300try {301writeReferenceField(null, field);302} catch (IOException exp) {303throw new RuntimeException(exp);304}305}306307public void doByte(ByteField field, boolean isVMField) {308try {309writeByteField(null, field);310} catch (IOException exp) {311throw new RuntimeException(exp);312}313}314315public void doChar(CharField field, boolean isVMField) {316try {317writeCharField(null, field);318} catch (IOException exp) {319throw new RuntimeException(exp);320}321}322323public void doBoolean(BooleanField field, boolean vField) {324try {325writeBooleanField(null, field);326} catch (IOException exp) {327throw new RuntimeException(exp);328}329}330331public void doShort(ShortField field, boolean isVMField) {332try {333writeShortField(null, field);334} catch (IOException exp) {335throw new RuntimeException(exp);336}337}338339public void doInt(IntField field, boolean isVMField) {340try {341writeIntField(null, field);342} catch (IOException exp) {343throw new RuntimeException(exp);344}345}346347public void doLong(LongField field, boolean isVMField) {348try {349writeLongField(null, field);350} catch (IOException exp) {351throw new RuntimeException(exp);352}353}354355public void doFloat(FloatField field, boolean isVMField) {356try {357writeFloatField(null, field);358} catch (IOException exp) {359throw new RuntimeException(exp);360}361}362363public void doDouble(DoubleField field, boolean vField) {364try {365writeDoubleField(null, field);366} catch (IOException exp) {367throw new RuntimeException(exp);368}369}370});371} catch (RuntimeException re) {372handleRuntimeException(re);373}374}375376// object field writers377protected void writeReferenceField(Oop oop, OopField field)378throws IOException {379}380381protected void writeByteField(Oop oop, ByteField field)382throws IOException {383}384385protected void writeCharField(Oop oop, CharField field)386throws IOException {387}388389protected void writeBooleanField(Oop oop, BooleanField field)390throws IOException {391}392393protected void writeShortField(Oop oop, ShortField field)394throws IOException {395}396397protected void writeIntField(Oop oop, IntField field)398throws IOException {399}400401protected void writeLongField(Oop oop, LongField field)402throws IOException {403}404405protected void writeFloatField(Oop oop, FloatField field)406throws IOException {407}408409protected void writeDoubleField(Oop oop, DoubleField field)410throws IOException {411}412413protected void writeObjectFooter(Oop oop) throws IOException {414}415416protected void writeHeapFooter() throws IOException {417}418419protected void writeHeapRecordPrologue() throws IOException {420}421422protected void writeHeapRecordEpilogue() throws IOException {423}424425// HeapVisitor, OopVisitor methods can't throw any non-runtime426// exception. But, derived class write methods (which are called427// from visitor callbacks) may throw IOException. Hence, we throw428// RuntimeException with origianal IOException as cause from the429// visitor methods. This method gets back the original IOException430// (if any) and re-throws the same.431protected void handleRuntimeException(RuntimeException re)432throws IOException {433Throwable cause = re.getCause();434if (cause != null && cause instanceof IOException) {435throw (IOException) cause;436} else {437// some other RuntimeException, just re-throw438throw re;439}440}441442// whether a given oop is Java visible or hotspot internal?443protected boolean isJavaVisible(Oop oop) {444if (oop instanceof Instance || oop instanceof TypeArray) {445return true;446} else if (oop instanceof ObjArray) {447ObjArrayKlass oak = (ObjArrayKlass) oop.getKlass();448Klass bottomKlass = oak.getBottomKlass();449return bottomKlass instanceof InstanceKlass ||450bottomKlass instanceof TypeArrayKlass;451} else {452return false;453}454}455456protected String javaLangClass;457protected String javaLangString;458protected String javaLangThread;459}460461462