1cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom/* 2cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Copyright (C) 2010 The Android Open Source Project 3cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * 4cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * you may not use this file except in compliance with the License. 6cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * You may obtain a copy of the License at 7cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * 8cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * 10cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Unless required by applicable law or agreed to in writing, software 11cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * See the License for the specific language governing permissions and 14cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * limitations under the License. 15cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 16cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 17cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrompackage dalvik.system.profiler; 18cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 19cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.io.DataOutputStream; 20cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.io.IOException; 21cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.io.OutputStream; 22cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.HashMap; 23cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Map; 24cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Set; 25cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 26e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom/** 27e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom * BinaryHprofWriter produces hprof compatible binary output for use 28e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom * with third party tools. Such files can be converted to text with 29e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom * with {@link HprofBinaryToAscii} or read back in with {@link BinaryHprofReader}. 30e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom */ 31e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrompublic final class BinaryHprofWriter { 32cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 33cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int nextStringId = 1; // id 0 => null 34cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int nextClassId = 1; 35cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int nextStackFrameId = 1; 36cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<String, Integer> stringToId = new HashMap<String, Integer>(); 37cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<String, Integer> classNameToId = new HashMap<String, Integer>(); 38cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<StackTraceElement, Integer> stackFrameToId 39cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom = new HashMap<StackTraceElement, Integer>(); 40cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 41cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final HprofData data; 42cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final DataOutputStream out; 43cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 44e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom /** 45e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom * Writes the provided data to the specified stream. 46e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom */ 47e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom public static void write(HprofData data, OutputStream outputStream) throws IOException { 48e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom new BinaryHprofWriter(data, outputStream).write(); 49e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom } 50e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom 51e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom private BinaryHprofWriter(HprofData data, OutputStream outputStream) { 52cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.data = data; 53cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.out = new DataOutputStream(outputStream); 54cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 55cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 56e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom private void write() throws IOException { 57cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom try { 58cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeHeader(data.getStartMillis()); 59cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 60cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeControlSettings(data.getFlags(), data.getDepth()); 61cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 62cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (HprofData.ThreadEvent event : data.getThreadHistory()) { 63cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeThreadEvent(event); 64cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 65cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 66cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom Set<HprofData.Sample> samples = data.getSamples(); 67cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int total = 0; 68cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (HprofData.Sample sample : samples) { 69cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom total += sample.count; 70cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeStackTrace(sample.stackTrace); 71cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 72cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeCpuSamples(total, samples); 73cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 74cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } finally { 75cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.flush(); 76cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 77cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 78cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 79cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeHeader(long dumpTimeInMilliseconds) throws IOException { 80e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom out.writeBytes(BinaryHprof.MAGIC + "1.0.2"); 81cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeByte(0); // null terminated string 82cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(BinaryHprof.ID_SIZE); 83cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeLong(dumpTimeInMilliseconds); 84cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 85cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 86cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeControlSettings(int flags, int depth) throws IOException { 87cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (depth > Short.MAX_VALUE) { 88cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalArgumentException("depth too large for binary hprof: " 89cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + depth + " > " + Short.MAX_VALUE); 90cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 91cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.CONTROL_SETTINGS, 92cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 0, 93cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom BinaryHprof.Tag.CONTROL_SETTINGS.maximumSize); 94cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(flags); 95cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeShort((short) depth); 96cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 97cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 98cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeThreadEvent(HprofData.ThreadEvent e) throws IOException { 99cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom switch (e.type) { 100cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case START: 101cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeStartThread(e); 102cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return; 103cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case END: 104cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeStopThread(e); 105cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return; 106cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 107cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalStateException(e.type.toString()); 108cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 109cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 110cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeStartThread(HprofData.ThreadEvent e) throws IOException { 111cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int threadNameId = writeString(e.threadName); 112cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int groupNameId = writeString(e.groupName); 113cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int parentGroupNameId = writeString(e.parentGroupName); 114cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.START_THREAD, 115cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 0, 116cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom BinaryHprof.Tag.START_THREAD.maximumSize); 117cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(e.threadId); 118cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(e.objectId); 119cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(0); // stack trace where thread was started unavailable 120cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(threadNameId); 121cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(groupNameId); 122cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(parentGroupNameId); 123cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 124cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 125cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeStopThread(HprofData.ThreadEvent e) throws IOException { 126cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.END_THREAD, 127cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 0, 128cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom BinaryHprof.Tag.END_THREAD.maximumSize); 129cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(e.threadId); 130cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 131cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 132cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeRecordHeader(BinaryHprof.Tag hprofTag, 133cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int timeDeltaInMicroseconds, 134cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int recordLength) throws IOException { 135cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String error = hprofTag.checkSize(recordLength); 136cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (error != null) { 137cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new AssertionError(error); 138cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 139cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeByte(hprofTag.tag); 140cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(timeDeltaInMicroseconds); 141cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(recordLength); 142cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 143cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 144cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeId(int id) throws IOException { 145cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(id); 146cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 147cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 148cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 149cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Ensures that a string has been writen to the out and 150cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * returns its ID. The ID of a null string is zero, and 151cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * doesn't actually result in any output. In a string has 152cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * already been written previously, the earlier ID will be 153cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * returned and no output will be written. 154cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 155cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int writeString(String string) throws IOException { 156cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (string == null) { 157cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return 0; 158cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 159cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom Integer identifier = stringToId.get(string); 160cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (identifier != null) { 161cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return identifier; 162cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 163cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 164cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int id = nextStringId++; 165cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom stringToId.put(string, id); 166cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 167cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom byte[] bytes = string.getBytes("UTF-8"); 168cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.STRING_IN_UTF8, 169cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 0, 170cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom BinaryHprof.ID_SIZE + bytes.length); 171cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(id); 172cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.write(bytes, 0, bytes.length); 173cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 174cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return id; 175cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 176cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 177cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeCpuSamples(int totalSamples, Set<HprofData.Sample> samples) 178cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throws IOException { 179cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int samplesCount = samples.size(); 180cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (samplesCount == 0) { 181cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return; 182cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 183cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.CPU_SAMPLES, 0, 4 + 4 + (samplesCount * (4 + 4))); 184cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(totalSamples); 185cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(samplesCount); 186cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (HprofData.Sample sample : samples) { 187cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(sample.count); 188cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(sample.stackTrace.stackTraceId); 189cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 190cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 191cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 192cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void writeStackTrace(HprofData.StackTrace stackTrace) throws IOException { 193cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int frames = stackTrace.stackFrames.length; 194cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int[] stackFrameIds = new int[frames]; 195cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (int i = 0; i < frames; i++) { 196cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom stackFrameIds[i] = writeStackFrame(stackTrace.stackFrames[i]); 197cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 198cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.STACK_TRACE, 199cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 0, 200cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 4 + 4 + 4 + (frames * BinaryHprof.ID_SIZE)); 201cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(stackTrace.stackTraceId); 202cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(stackTrace.threadId); 203cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(frames); 204cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (int stackFrameId : stackFrameIds) { 205cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(stackFrameId); 206cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 207cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 208cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 209cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int writeLoadClass(String className) throws IOException { 210cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom Integer identifier = classNameToId.get(className); 211cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (identifier != null) { 212cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return identifier; 213cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 214cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int id = nextClassId++; 215cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom classNameToId.put(className, id); 216cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 217cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int classNameId = writeString(className); 218cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.LOAD_CLASS, 219cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 0, 220cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom BinaryHprof.Tag.LOAD_CLASS.maximumSize); 221cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(id); 222cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(0); // class object ID 223cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(0); // stack trace where class was loaded is unavailable 224cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(classNameId); 225cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 226cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return id; 227cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 228cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 229cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int writeStackFrame(StackTraceElement stackFrame) throws IOException { 230cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom Integer identifier = stackFrameToId.get(stackFrame); 231cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (identifier != null) { 232cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return identifier; 233cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 234cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 235cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int id = nextStackFrameId++; 236cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom stackFrameToId.put(stackFrame, id); 237cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 238cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int classId = writeLoadClass(stackFrame.getClassName()); 239cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int methodNameId = writeString(stackFrame.getMethodName()); 240cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int sourceId = writeString(stackFrame.getFileName()); 241cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeRecordHeader(BinaryHprof.Tag.STACK_FRAME, 242cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 0, 243cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom BinaryHprof.Tag.STACK_FRAME.maximumSize); 244cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(id); 245cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(methodNameId); 246cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(0); // method signature is unavailable from StackTraceElement 247cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom writeId(sourceId); 248cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(classId); 249cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom out.writeInt(stackFrame.getLineNumber()); 250cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 251cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return id; 252cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 253cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom} 254