diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java index 4d34f9912df..947701c9c3b 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -44,10 +44,14 @@ public class ClassLoaderData extends VMObject { Type type = db.lookupType("ClassLoaderData"); classLoaderField = type.getOopField("_class_loader"); nextField = type.getAddressField("_next"); + klassesField = type.getAddressField("_klasses"); + isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0); } private static sun.jvm.hotspot.types.OopField classLoaderField; private static AddressField nextField; + private static AddressField klassesField; + private static CIntField isAnonymousField; public ClassLoaderData(Address addr) { super(addr); @@ -63,4 +67,16 @@ public class ClassLoaderData extends VMObject { public Oop getClassLoader() { return VM.getVM().getObjectHeap().newOop(classLoaderField.getValue(getAddress())); } + + public boolean getIsAnonymous() { + return isAnonymousField.getValue(this) != 0; + } + + public ClassLoaderData next() { + return instantiateWrapperFor(nextField.getValue(getAddress())); + } + + public Klass getKlasses() { + return (InstanceKlass)Metadata.instantiateWrapperFor(klassesField.getValue(getAddress())); + } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java new file mode 100644 index 00000000000..fbc9a76401d --- /dev/null +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, 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.classfile; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ClassLoaderDataGraph { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ClassLoaderDataGraph"); + + headField = type.getAddressField("_head"); + } + + private static AddressField headField; + + public ClassLoaderData getClassLoaderGraphHead() { + return ClassLoaderData.instantiateWrapperFor(headField.getValue()); + } + + public static interface KlassVisitor { + public void visit(Klass k); + } + + /** Iterate over all anonymous class loaders and the klasses in those */ + public void allAnonymousKlassesDo(final KlassVisitor v) { + for (ClassLoaderData cl = getClassLoaderGraphHead(); + cl != null; + cl = cl.next()) { + if (cl.getIsAnonymous() == true) { + for (Klass k = cl.getKlasses(); k != null; k = k.getNextLinkKlass()) { + v.visit(k); + } + } + } + } + +} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java index b5d93a852a7..afa00274f1d 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java @@ -61,6 +61,7 @@ public class Klass extends Metadata implements ClassConstants { } subklass = new MetadataField(type.getAddressField("_subklass"), 0); nextSibling = new MetadataField(type.getAddressField("_next_sibling"), 0); + nextLink = new MetadataField(type.getAddressField("_next_link"), 0); vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0); LH_INSTANCE_SLOW_PATH_BIT = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue(); @@ -92,6 +93,7 @@ public class Klass extends Metadata implements ClassConstants { private static CIntField accessFlags; private static MetadataField subklass; private static MetadataField nextSibling; + private static MetadataField nextLink; private static sun.jvm.hotspot.types.Field traceIDField; private static CIntField vtableLen; @@ -114,6 +116,7 @@ public class Klass extends Metadata implements ClassConstants { public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); } public Klass getSubklassKlass() { return (Klass) subklass.getValue(this); } public Klass getNextSiblingKlass() { return (Klass) nextSibling.getValue(this); } + public Klass getNextLinkKlass() { return (Klass) nextLink.getValue(this); } public long getVtableLen() { return vtableLen.getValue(this); } public long traceID() { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java index 22bdcf99638..bd4934560a6 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -38,6 +38,7 @@ import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.classfile.*; /**
This class encapsulates the global state of the VM; the
universe, object heap, interpreter, etc. It is a Singleton and
@@ -80,6 +81,7 @@ public class VM {
private SymbolTable symbols;
private StringTable strings;
private SystemDictionary dict;
+ private ClassLoaderDataGraph cldGraph;
private Threads threads;
private ObjectSynchronizer synchronizer;
private JNIHandles handles;
@@ -660,6 +662,13 @@ public class VM {
return dict;
}
+ public ClassLoaderDataGraph getClassLoaderDataGraph() {
+ if (cldGraph == null) {
+ cldGraph = new ClassLoaderDataGraph();
+ }
+ return cldGraph;
+ }
+
public Threads getThreads() {
if (threads == null) {
threads = new Threads();
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java
index 319aecdaa31..9da43745388 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, 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
@@ -31,6 +31,7 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.classfile.*;
/*
* This class writes Java heap in hprof binary format. This format is
@@ -379,6 +380,8 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
private static final int JVM_SIGNATURE_ARRAY = '[';
private static final int JVM_SIGNATURE_CLASS = 'L';
+ int serialNum = 1;
+
public synchronized void write(String fileName) throws IOException {
// open file stream and create buffered data output stream
fos = new FileOutputStream(fileName);
@@ -516,6 +519,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
private void writeClassDumpRecords() throws IOException {
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
+ ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
try {
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
public void visit(Klass k) {
@@ -528,6 +532,19 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
}
}
});
+ // Add the anonymous classes also which are not present in the
+ // System Dictionary
+ cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
+ public void visit(Klass k) {
+ try {
+ writeHeapRecordPrologue();
+ writeClassDumpRecord(k);
+ writeHeapRecordEpilogue();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
} catch (RuntimeException re) {
handleRuntimeException(re);
}
@@ -799,17 +816,6 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
writeObjectID(klass.getJavaMirror());
ClassData cd = (ClassData) classDataCache.get(klass);
- if (cd == null) {
- // The class is not present in the system dictionary, probably Lambda.
- // Add it to cache here
- if (klass instanceof InstanceKlass) {
- InstanceKlass ik = (InstanceKlass) klass;
- List fields = getInstanceFields(ik);
- int instSize = getSizeForFields(fields);
- cd = new ClassData(instSize, fields);
- classDataCache.put(ik, cd);
- }
- }
if (Assert.ASSERTS_ENABLED) {
Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getAddress());
@@ -950,9 +956,24 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
private void writeClasses() throws IOException {
// write class list (id, name) association
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
+ ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
try {
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
- private int serialNum = 1;
+ public void visit(Klass k) {
+ try {
+ Instance clazz = k.getJavaMirror();
+ writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
+ out.writeInt(serialNum);
+ writeObjectID(clazz);
+ out.writeInt(DUMMY_STACK_TRACE_ID);
+ writeSymbolID(k.getName());
+ serialNum++;
+ } catch (IOException exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ });
+ cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
public void visit(Klass k) {
try {
Instance clazz = k.getJavaMirror();
diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp
index c9ac7e9755f..46824eb7553 100644
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp
@@ -288,7 +288,8 @@ typedef CompactHashtable