Home | History | Annotate | Download | only in profiler
      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      */
     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 
     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()) {
    109                 BYTE_TO_TAG.put(v.tag, v);
    110             }
    111         }
    112 
    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          */
    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 
    143         private ControlSettings(int bitmask) {
    144             this.bitmask = bitmask;
    145         }
    146     }
    147 
    148 }
    149