1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dalvik.system.profiler; 18 19 import java.io.DataInputStream; 20 import java.io.IOException; 21 import java.util.HashMap; 22 import java.util.Map; 23 24 /** 25 * Hprof binary format related constants shared between the 26 * BinaryHprofReader and BinaryHprofWriter. 27 */ 28 public final class BinaryHprof { 29 /** 30 * Currently code only supports 4 byte id size. 31 */ 32 public static final int ID_SIZE = 4; 33 34 /** 35 * Prefix of valid magic values from the start of a binary hprof file. 36 */ 37 static String MAGIC = "JAVA PROFILE "; 38 39 /** 40 * Returns the file's magic value as a String if found, otherwise null. 41 */ readMagic(DataInputStream in)42 public static final String readMagic(DataInputStream in) { 43 try { 44 byte[] bytes = new byte[512]; 45 for (int i = 0; i < bytes.length; i++) { 46 byte b = in.readByte(); 47 if (b == '\0') { 48 String string = new String(bytes, 0, i, "UTF-8"); 49 if (string.startsWith(MAGIC)) { 50 return string; 51 } 52 return null; 53 } 54 bytes[i] = b; 55 } 56 return null; 57 } catch (IOException e) { 58 return null; 59 } 60 } 61 62 public static enum Tag { 63 64 STRING_IN_UTF8(0x01, -ID_SIZE), 65 LOAD_CLASS(0x02, 4 + ID_SIZE + 4 + ID_SIZE), 66 UNLOAD_CLASS(0x03, 4), 67 STACK_FRAME(0x04, ID_SIZE + ID_SIZE + ID_SIZE + ID_SIZE + 4 + 4), 68 STACK_TRACE(0x05, -(4 + 4 + 4)), 69 ALLOC_SITES(0x06, -(2 + 4 + 4 + 4 + 8 + 8 + 4)), 70 HEAP_SUMMARY(0x07, 4 + 4 + 8 + 8), 71 START_THREAD(0x0a, 4 + ID_SIZE + 4 + ID_SIZE + ID_SIZE + ID_SIZE), 72 END_THREAD(0x0b, 4), 73 HEAP_DUMP(0x0c, -0), 74 HEAP_DUMP_SEGMENT(0x1c, -0), 75 HEAP_DUMP_END(0x2c, 0), 76 CPU_SAMPLES(0x0d, -(4 + 4)), 77 CONTROL_SETTINGS(0x0e, 4 + 2); 78 79 public final byte tag; 80 81 /** 82 * Minimum size in bytes. 83 */ 84 public final int minimumSize; 85 86 /** 87 * Maximum size in bytes. 0 mean no specific limit. 88 */ 89 public final int maximumSize; 90 Tag(int tag, int size)91 private Tag(int tag, int size) { 92 this.tag = (byte) tag; 93 if (size > 0) { 94 // fixed size, max and min the same 95 this.minimumSize = size; 96 this.maximumSize = size; 97 } else { 98 // only minimum bound 99 this.minimumSize = -size; 100 this.maximumSize = 0; 101 } 102 } 103 104 private static final Map<Byte, Tag> BYTE_TO_TAG 105 = new HashMap<Byte, Tag>(); 106 107 static { 108 for (Tag v : Tag.values()) { BYTE_TO_TAG.put(v.tag, v)109 BYTE_TO_TAG.put(v.tag, v); 110 } 111 } 112 get(byte tag)113 public static Tag get(byte tag) { 114 return BYTE_TO_TAG.get(tag); 115 } 116 117 /** 118 * Returns null if the actual size meets expectations, or a 119 * String error message if not. 120 */ checkSize(int actual)121 public String checkSize(int actual) { 122 if (actual < minimumSize) { 123 return "expected a minimial record size of " + minimumSize + " for " + this 124 + " but received " + actual; 125 } 126 if (maximumSize == 0) { 127 return null; 128 } 129 if (actual > maximumSize) { 130 return "expected a maximum record size of " + maximumSize + " for " + this 131 + " but received " + actual; 132 } 133 return null; 134 } 135 } 136 137 public static enum ControlSettings { 138 ALLOC_TRACES(0x01), 139 CPU_SAMPLING(0x02); 140 141 public final int bitmask; 142 ControlSettings(int bitmask)143 private ControlSettings(int bitmask) { 144 this.bitmask = bitmask; 145 } 146 } 147 148 } 149