blob: 9720446f8acf1ef75890dbd807eb361f6ae8f108 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dalvik.system.profiler;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Hprof binary format related constants shared between the
* BinaryHprofReader and BinaryHprofWriter.
*/
public final class BinaryHprof {
/**
* Currently code only supports 4 byte id size.
*/
public static final int ID_SIZE = 4;
/**
* Prefix of valid magic values from the start of a binary hprof file.
*/
static String MAGIC = "JAVA PROFILE ";
/**
* Returns the file's magic value as a String if found, otherwise null.
*/
public static final String readMagic(DataInputStream in) {
try {
byte[] bytes = new byte[512];
for (int i = 0; i < bytes.length; i++) {
byte b = in.readByte();
if (b == '\0') {
String string = new String(bytes, 0, i, "UTF-8");
if (string.startsWith(MAGIC)) {
return string;
}
return null;
}
bytes[i] = b;
}
return null;
} catch (IOException e) {
return null;
}
}
public static enum Tag {
STRING_IN_UTF8(0x01, -ID_SIZE),
LOAD_CLASS(0x02, 4 + ID_SIZE + 4 + ID_SIZE),
UNLOAD_CLASS(0x03, 4),
STACK_FRAME(0x04, ID_SIZE + ID_SIZE + ID_SIZE + ID_SIZE + 4 + 4),
STACK_TRACE(0x05, -(4 + 4 + 4)),
ALLOC_SITES(0x06, -(2 + 4 + 4 + 4 + 8 + 8 + 4)),
HEAP_SUMMARY(0x07, 4 + 4 + 8 + 8),
START_THREAD(0x0a, 4 + ID_SIZE + 4 + ID_SIZE + ID_SIZE + ID_SIZE),
END_THREAD(0x0b, 4),
HEAP_DUMP(0x0c, -0),
HEAP_DUMP_SEGMENT(0x1c, -0),
HEAP_DUMP_END(0x2c, 0),
CPU_SAMPLES(0x0d, -(4 + 4)),
CONTROL_SETTINGS(0x0e, 4 + 2);
public final byte tag;
/**
* Minimum size in bytes.
*/
public final int minimumSize;
/**
* Maximum size in bytes. 0 mean no specific limit.
*/
public final int maximumSize;
private Tag(int tag, int size) {
this.tag = (byte) tag;
if (size > 0) {
// fixed size, max and min the same
this.minimumSize = size;
this.maximumSize = size;
} else {
// only minimum bound
this.minimumSize = -size;
this.maximumSize = 0;
}
}
private static final Map<Byte, Tag> BYTE_TO_TAG
= new HashMap<Byte, Tag>();
static {
for (Tag v : Tag.values()) {
BYTE_TO_TAG.put(v.tag, v);
}
}
public static Tag get(byte tag) {
return BYTE_TO_TAG.get(tag);
}
/**
* Returns null if the actual size meets expectations, or a
* String error message if not.
*/
public String checkSize(int actual) {
if (actual < minimumSize) {
return "expected a minimial record size of " + minimumSize + " for " + this
+ " but received " + actual;
}
if (maximumSize == 0) {
return null;
}
if (actual > maximumSize) {
return "expected a maximum record size of " + maximumSize + " for " + this
+ " but received " + actual;
}
return null;
}
}
public static enum ControlSettings {
ALLOC_TRACES(0x01),
CPU_SAMPLING(0x02);
public final int bitmask;
private ControlSettings(int bitmask) {
this.bitmask = bitmask;
}
}
}