--- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java 2018-06-22 15:05:29.469104300 -0400 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java 2018-06-22 15:05:29.257104307 -0400 @@ -309,6 +309,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter { + // Record which Symbol names have been dumped already. + private HashSet names; + private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000; // The approximate size of a heap segment. Used to calculate when to create @@ -381,6 +384,7 @@ public HeapHprofBinWriter() { this.KlassMap = new ArrayList(); + this.names = new HashSet(); } public synchronized void write(String fileName) throws IOException { @@ -391,7 +395,6 @@ VM vm = VM.getVM(); dbg = vm.getDebugger(); objectHeap = vm.getObjectHeap(); - symTbl = vm.getSymbolTable(); OBJ_ID_SIZE = (int) vm.getOopSize(); @@ -745,6 +748,11 @@ } else { lineNumber = m.getLineNumberFromBCI(bci); } + // First dump UTF8 if needed + writeSymbol(m.getName()); // method's name + writeSymbol(m.getSignature()); // method's signature + writeSymbol(m.getMethodHolder().getSourceFileName()); // source file name + // Then write FRAME descriptor writeHeader(HPROF_FRAME, 4 * (int)VM.getVM().getOopSize() + 2 * (int)INT_SIZE); writeObjectID(frameSN); // frame serial number writeSymbolID(m.getName()); // method's name @@ -955,7 +963,7 @@ out.writeShort((short) fields.size()); for (Iterator itr = fields.iterator(); itr.hasNext();) { Field field = (Field) itr.next(); - Symbol name = symTbl.probe(field.getID().getName()); + Symbol name = field.getName(); writeSymbolID(name); char typeCode = (char) field.getSignature().getByteAt(0); int kind = signatureToHprofKind(typeCode); @@ -1049,27 +1057,44 @@ out.writeInt(0); } + private void writeClassSymbols(Klass k) throws IOException { + writeSymbol(k.getName()); + if (k instanceof InstanceKlass) { + InstanceKlass ik = (InstanceKlass) k; + List declaredFields = ik.getImmediateFields(); + for (Iterator itr = declaredFields.iterator(); itr.hasNext();) { + Field field = (Field) itr.next(); + writeSymbol(field.getName()); + } + } + } + private void writeSymbols() throws IOException { + // Write all the symbols that are used by the classes + ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph(); try { - symTbl.symbolsDo(new SymbolTable.SymbolVisitor() { - public void visit(Symbol sym) { - try { - writeSymbol(sym); - } catch (IOException exp) { - throw new RuntimeException(exp); - } - } - }); + cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() { + public void visit(Klass k) { + try { + writeClassSymbols(k); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); } catch (RuntimeException re) { handleRuntimeException(re); } } private void writeSymbol(Symbol sym) throws IOException { - byte[] buf = sym.asString().getBytes("UTF-8"); - writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE); - writeSymbolID(sym); - out.write(buf); + // If name is already written don't write it again. + if (names.add(sym)) { + byte[] buf = sym.asString().getBytes("UTF-8"); + writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE); + writeSymbolID(sym); + out.write(buf); + } } private void writeClasses() throws IOException { @@ -1118,6 +1143,7 @@ } private void writeSymbolID(Symbol sym) throws IOException { + assert names.contains(sym); writeObjectID(getAddressValue(sym.getAddress())); } @@ -1195,7 +1221,6 @@ private FileOutputStream fos; private Debugger dbg; private ObjectHeap objectHeap; - private SymbolTable symTbl; private ArrayList KlassMap; // oopSize of the debuggee