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.BufferedInputStream; 20cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.io.DataInputStream; 21cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.io.EOFException; 22cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.io.IOException; 23cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.io.InputStream; 24cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Date; 25cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.HashMap; 26cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstromimport java.util.Map; 27cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 28cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom/** 29cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * <pre> {@code 30cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * BinaryHprofReader reader = new BinaryHprofReader(new BufferedInputStream(inputStream)); 31cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * reader.setStrict(false); // for RI compatability 32cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * reader.read(); 33cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * inputStream.close(); 34cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * reader.getVersion(); 35cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * reader.getHprofData(); 36cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * }</pre> 37cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 38cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrompublic final class BinaryHprofReader { 39cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 40cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private static final boolean TRACE = false; 41cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 42cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final DataInputStream in; 43cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 44cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 45cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * By default we try to strictly validate rules followed by 46cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * our HprofWriter. For example, every end thread is preceded 47cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * by a matching start thread. 48cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 49cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private boolean strict = true; 50cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 51cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 52cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * version string from header after read has been performed, 53cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * otherwise null. nullness used to detect if callers try to 54cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * access data before read is called. 55cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 56cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private String version; 57cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 58cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<HprofData.StackTrace, int[]> stackTraces 59cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom = new HashMap<HprofData.StackTrace, int[]>(); 60cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 61cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final HprofData hprofData = new HprofData(stackTraces); 62cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 63cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<Integer, String> idToString = new HashMap<Integer, String>(); 64cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<Integer, String> idToClassName = new HashMap<Integer, String>(); 65cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<Integer, StackTraceElement> idToStackFrame 66cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom = new HashMap<Integer, StackTraceElement>(); 67cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private final Map<Integer, HprofData.StackTrace> idToStackTrace 68cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom = new HashMap<Integer, HprofData.StackTrace>(); 69cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 70cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 71cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Creates a BinaryHprofReader around the specified {@code 72cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * inputStream} 73cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 74cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public BinaryHprofReader(InputStream inputStream) throws IOException { 75cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.in = new DataInputStream(inputStream); 76cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 77cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 78cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public boolean getStrict () { 79cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return strict; 80cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 81cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 82cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public void setStrict (boolean strict) { 83cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (version != null) { 84cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalStateException("cannot set strict after read()"); 85cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 86cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom this.strict = strict; 87cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 88cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 89cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 90cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * throws IllegalStateException if read() has not been called. 91cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 92cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void checkRead() { 93cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (version == null) { 94cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new IllegalStateException("data access before read()"); 95cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 96cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 97cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 98cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public String getVersion() { 99cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom checkRead(); 100cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return version; 101cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 102cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 103cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public HprofData getHprofData() { 104cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom checkRead(); 105cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return hprofData; 106cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 107cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 108cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 109cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Read the hprof header and records from the input 110cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 111cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom public void read() throws IOException { 112cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseHeader(); 113cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseRecords(); 114cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 115cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 116cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseHeader() throws IOException { 117cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 118cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("hprofTag=HEADER"); 119cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 120cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseVersion(); 121cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseIdSize(); 122cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseTime(); 123cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 124cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 125cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseVersion() throws IOException { 126e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom String version = BinaryHprof.readMagic(in); 127e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom if (version == null) { 128e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom throw new MalformedHprofException("Could not find HPROF version"); 129e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom } 130e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom if (TRACE) { 131e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom System.out.println("\tversion=" + version); 132cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 133e9af8901fc4ed7c05d085e2e492f5dcc857f0146Brian Carlstrom this.version = version; 134cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 135cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 136cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseIdSize() throws IOException { 137cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int idSize = in.readInt(); 138cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 139cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tidSize=" + idSize); 140cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 141cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (idSize != BinaryHprof.ID_SIZE) { 142cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Unsupported identifier size: " + idSize); 143cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 144cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 145cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 146cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseTime() throws IOException { 147cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom long time = in.readLong(); 148cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 149cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\ttime=" + Long.toHexString(time) + " " + new Date(time)); 150cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 151cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom hprofData.setStartMillis(time); 152cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 153cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 154cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseRecords() throws IOException { 155cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom while (parseRecord()) { 156cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom ; 157cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 158cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 159cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 160cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom /** 161cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * Read and process the next record. Returns true if a 162cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom * record was handled, false on EOF. 163cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom */ 164cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private boolean parseRecord() throws IOException { 165cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int tagOrEOF = in.read(); 166cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (tagOrEOF == -1) { 167cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return false; 168cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 169cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom byte tag = (byte) tagOrEOF; 170cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int timeDeltaInMicroseconds = in.readInt(); 171cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int recordLength = in.readInt(); 172cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom BinaryHprof.Tag hprofTag = BinaryHprof.Tag.get(tag); 173cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 174cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("hprofTag=" + hprofTag); 175cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 176cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (hprofTag == null) { 177cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom skipRecord(hprofTag, recordLength); 178cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 179cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 180cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String error = hprofTag.checkSize(recordLength); 181cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (error != null) { 182cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException(error); 183cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 184cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom switch (hprofTag) { 185cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case CONTROL_SETTINGS: 186cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseControlSettings(); 187cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 188cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 189cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case STRING_IN_UTF8: 190cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseStringInUtf8(recordLength); 191cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 192cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 193cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case START_THREAD: 194cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseStartThread(); 195cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 196cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case END_THREAD: 197cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseEndThread(); 198cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 199cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 200cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case LOAD_CLASS: 201cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseLoadClass(); 202cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 203cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case STACK_FRAME: 204cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseStackFrame(); 205cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 206cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case STACK_TRACE: 207cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseStackTrace(recordLength); 208cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 209cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 210cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case CPU_SAMPLES: 211cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom parseCpuSamples(recordLength); 212cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 213cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 214cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case UNLOAD_CLASS: 215cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case ALLOC_SITES: 216cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case HEAP_SUMMARY: 217cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case HEAP_DUMP: 218cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case HEAP_DUMP_SEGMENT: 219cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom case HEAP_DUMP_END: 220cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom default: 221cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom skipRecord(hprofTag, recordLength); 222cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return true; 223cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 224cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 225cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 226cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void skipRecord(BinaryHprof.Tag hprofTag, long recordLength) throws IOException { 227cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 228cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tskipping recordLength=" + recordLength); 229cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 230cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom long skipped = in.skip(recordLength); 231cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (skipped != recordLength) { 232cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new EOFException("Expected to skip " + recordLength 233cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + " bytes but only skipped " + skipped + " bytes"); 234cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 235cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 236cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 237cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseControlSettings() throws IOException { 238cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int flags = in.readInt(); 239cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom short depth = in.readShort(); 240cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 241cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tflags=" + Integer.toHexString(flags)); 242cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tdepth=" + depth); 243cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 244cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom hprofData.setFlags(flags); 245cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom hprofData.setDepth(depth); 246cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 247cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 248cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseStringInUtf8(int recordLength) throws IOException { 249cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int stringId = in.readInt(); 250cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom byte[] bytes = new byte[recordLength - BinaryHprof.ID_SIZE]; 251cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom readFully(in, bytes); 252cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String string = new String(bytes, "UTF-8"); 253cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 254cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstring=" + string); 255cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 256cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String old = idToString.put(stringId, string); 257cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (old != null) { 258cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Duplicate string id: " + stringId); 259cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 260cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 261cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 262cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private static void readFully(InputStream in, byte[] dst) throws IOException { 263cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int offset = 0; 264cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int byteCount = dst.length; 265cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom while (byteCount > 0) { 266cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int bytesRead = in.read(dst, offset, byteCount); 267cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (bytesRead < 0) { 268cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new EOFException(); 269cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 270cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom offset += bytesRead; 271cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom byteCount -= bytesRead; 272cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 273cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 274cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 275cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseLoadClass() throws IOException { 276cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int classId = in.readInt(); 277cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int classObjectId = readId(); 278cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // serial number apparently not a stack trace id. (int vs ID) 279cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // we don't use this field. 280cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int stackTraceSerialNumber = in.readInt(); 281cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String className = readString(); 282cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 283cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tclassId=" + classId); 284cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tclassObjectId=" + classObjectId); 285cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstackTraceSerialNumber=" + stackTraceSerialNumber); 286cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tclassName=" + className); 287cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 288cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String old = idToClassName.put(classId, className); 289cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (old != null) { 290cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Duplicate class id: " + classId); 291cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 292cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 293cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 294cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private int readId() throws IOException { 295cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return in.readInt(); 296cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 297cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 298cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private String readString() throws IOException { 299cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int id = readId(); 300cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (id == 0) { 301cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return null; 302cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 303cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String string = idToString.get(id); 304cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (string == null) { 305cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Unknown string id " + id); 306cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 307cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return string; 308cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 309cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 310cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private String readClass() throws IOException { 311cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int id = readId(); 312cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String string = idToClassName.get(id); 313cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (string == null) { 314cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Unknown class id " + id); 315cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 316cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom return string; 317cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 318cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 319cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseStartThread() throws IOException { 320cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int threadId = in.readInt(); 321cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int objectId = readId(); 322cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // stack trace where thread was created. 323cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // serial number apparently not a stack trace id. (int vs ID) 324cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // we don't use this field. 325cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int stackTraceSerialNumber = in.readInt(); 326cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String threadName = readString(); 327cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String groupName = readString(); 328cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String parentGroupName = readString(); 329cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 330cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tthreadId=" + threadId); 331cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tobjectId=" + objectId); 332cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstackTraceSerialNumber=" + stackTraceSerialNumber); 333cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tthreadName=" + threadName); 334cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tgroupName=" + groupName); 335cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tparentGroupName=" + parentGroupName); 336cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 337cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom HprofData.ThreadEvent event 338cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom = HprofData.ThreadEvent.start(objectId, threadId, 339cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom threadName, groupName, parentGroupName); 340cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom hprofData.addThreadEvent(event); 341cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 342cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 343cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseEndThread() throws IOException { 344cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int threadId = in.readInt(); 345cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 346cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tthreadId=" + threadId); 347cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 348cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom HprofData.ThreadEvent event = HprofData.ThreadEvent.end(threadId); 349cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom hprofData.addThreadEvent(event); 350cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 351cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 352cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseStackFrame() throws IOException { 353cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int stackFrameId = readId(); 354cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String methodName = readString(); 355cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String methodSignature = readString(); 356cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String file = readString(); 357cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom String className = readClass(); 358cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int line = in.readInt(); 359cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 360cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstackFrameId=" + stackFrameId); 361cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tclassName=" + className); 362cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tmethodName=" + methodName); 363cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tmethodSignature=" + methodSignature); 364cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tfile=" + file); 365cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tline=" + line); 366cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 367cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTraceElement stackFrame = new StackTraceElement(className, methodName, file, line); 368cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTraceElement old = idToStackFrame.put(stackFrameId, stackFrame); 369cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (old != null) { 370cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Duplicate stack frame id: " + stackFrameId); 371cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 372cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 373cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 374cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseStackTrace(int recordLength) throws IOException { 375cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int stackTraceId = in.readInt(); 376cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int threadId = in.readInt(); 377cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int frames = in.readInt(); 378cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 379cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstackTraceId=" + stackTraceId); 380cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tthreadId=" + threadId); 381cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tframes=" + frames); 382cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 383cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int expectedLength = 4 + 4 + 4 + (frames * BinaryHprof.ID_SIZE); 384cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (recordLength != expectedLength) { 385cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Expected stack trace record of size " 386cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + expectedLength 387cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + " based on number of frames but header " 388cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + "specified a length of " + recordLength); 389cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 390cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTraceElement[] stackFrames = new StackTraceElement[frames]; 391cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (int i = 0; i < frames; i++) { 392cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int stackFrameId = readId(); 393cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom StackTraceElement stackFrame = idToStackFrame.get(stackFrameId); 394cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 395cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstackFrameId=" + stackFrameId); 396cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstackFrame=" + stackFrame); 397cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 398cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (stackFrame == null) { 399cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Unknown stack frame id " + stackFrameId); 400cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 401cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom stackFrames[i] = stackFrame; 402cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 403cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 404cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom HprofData.StackTrace stackTrace 405cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom = new HprofData.StackTrace(stackTraceId, threadId, stackFrames); 406cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (strict) { 407cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom hprofData.addStackTrace(stackTrace, new int[1]); 408cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } else { 409cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // The RI can have duplicate stacks, presumably they 410cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // have a minor race if two samples with the same 411cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // stack are taken around the same time. if we have a 412cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // duplicate, just skip adding it to hprofData, but 413cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // register it locally in idToStackFrame. if it seen 414cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // in CPU_SAMPLES, we will find a StackTrace is equal 415cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // to the first, so they will share a countCell. 416cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int[] countCell = stackTraces.get(stackTrace); 417cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (countCell == null) { 418cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom hprofData.addStackTrace(stackTrace, new int[1]); 419cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 420cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 421cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 422cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom HprofData.StackTrace old = idToStackTrace.put(stackTraceId, stackTrace); 423cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (old != null) { 424cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Duplicate stack trace id: " + stackTraceId); 425cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 426cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 427cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 428cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom 429cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom private void parseCpuSamples(int recordLength) throws IOException { 430cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int totalSamples = in.readInt(); 431cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int samplesCount = in.readInt(); 432cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 433cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\ttotalSamples=" + totalSamples); 434cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tsamplesCount=" + samplesCount); 435cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 436cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int expectedLength = 4 + 4 + (samplesCount * (4 + 4)); 437cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (recordLength != expectedLength) { 438cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Expected CPU samples record of size " 439cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + expectedLength 440cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + " based on number of samples but header " 441cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + "specified a length of " + recordLength); 442cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 443cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int total = 0; 444cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom for (int i = 0; i < samplesCount; i++) { 445cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int count = in.readInt(); 446cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int stackTraceId = in.readInt(); 447cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (TRACE) { 448cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tcount=" + count); 449cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom System.out.println("\tstackTraceId=" + stackTraceId); 450cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 451cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom HprofData.StackTrace stackTrace = idToStackTrace.get(stackTraceId); 452cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (stackTrace == null) { 453cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Unknown stack trace id " + stackTraceId); 454cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 455cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (count == 0) { 456cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Zero sample count for stack trace " 457cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + stackTrace); 458cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 459cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom int[] countCell = stackTraces.get(stackTrace); 460cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (strict) { 461cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (countCell[0] != 0) { 462cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Setting sample count of stack trace " 463cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + stackTrace + " to " + count 464cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + " found it was already initialized to " 465cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + countCell[0]); 466cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 467cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } else { 468cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // Coalesce counts from duplicate stack traces. 469cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom // For more on this, see comments in parseStackTrace. 470cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom count += countCell[0]; 471cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 472cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom countCell[0] = count; 473cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom total += count; 474cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 475cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom if (strict && totalSamples != total) { 476cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom throw new MalformedHprofException("Expected a total of " + totalSamples 477cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom + " samples but saw " + total); 478cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 479cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom } 480cfa84a2aac159bb8a1763298882df7aa98f7fc6fBrian Carlstrom} 481