Package org.apache.kato.hprof.datalayer

Source Code of org.apache.kato.hprof.datalayer.HProfFile$UnloadClassHProfRecord

/*******************************************************************************
* 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 org.apache.kato.hprof.datalayer;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.kato.common.BitMaskMappingArray;
import org.apache.kato.common.DataProviderBackedArrayProvider;
import org.apache.kato.common.DataReader;
import org.apache.kato.common.IArrayEntryProvider;
import org.apache.kato.common.IDataProvider;
import org.apache.kato.common.InvalidFileFormat;
import org.apache.kato.common.SubsetDataProvider;
import org.apache.kato.hprof.HProfRecordFormatter;
public class HProfFile {

  class ControlSettingsHProfRecord extends HProfRecord implements
      IControlSettingsHProfRecord {

    public ControlSettingsHProfRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public short getStackTraceDepth() {
      return readShort(4);
    }

    public boolean isAllocTrace() {
      return (readInt(0) & 1) == 1;
    }

    public boolean isCpuSampling() {
      return (readInt(0) & 2) == 2;
    }
  }

  class EndThreadHProfRecord extends HProfRecord implements
      IThreadEndingHProfRecord {

    public EndThreadHProfRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public int getThreadSerialNumber() {
      return readInt(0);
    }
  }

  class FrameHProfRecord extends HProfRecord implements
      IJavaStackFrameHProfRecord {

    public FrameHProfRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public int getClassSerialNumber() {
      return readInt(idSize * 4);
    }

    public int getLineNumber() {
      return readInt((idSize * 4) + 4);
    }

    public long getMethodNameID() {
      return readNumber(idSize, idSize);
    }

    public long getMethodSignatureID() {
      return readNumber(idSize + idSize, idSize);
    }

    public long getSourceFileNameID() {
      return readNumber(idSize + idSize + idSize, idSize);
    }

    public long getStackFrameID() {
      return readNumber(0, idSize);
    }

    /**
     * Check equality based on stack frame ID.
     */
    public boolean equals(Object obj) {
      if ((obj == null) || !(obj instanceof FrameHProfRecord)) {
        return false;
      }
     
      FrameHProfRecord record = (FrameHProfRecord) obj;
     
      return record.getStackFrameID() == getStackFrameID();
    }

  }

  class HeapDumpHProfRecord extends HProfRecord implements
      IHeapDumpHProfRecord {

    private BitMaskMappingArray subRecordArray = null;
    private int subRecordCount = -1;
    private long size = 0;
    private IDataProvider myP = null;

    public HeapDumpHProfRecord(short tag, IDataProvider dataProvider)
        throws IOException {
      super(tag, null);
      size = dataProvider.getDataLength();
      myP = dataProvider;
      subRecordArray = new BitMaskMappingArray(1000, 25,
          new HProfDumpRecordArrayProvider(dataProvider));
    }

    public IHProfRecord getSubRecord(int index) {

      return (IHProfRecord) subRecordArray.get(index);
    }

    @Override
    public int getSubRecordCount() {
      if (subRecordCount == -1) {

        subRecordCount = 0;
        while (true) {
          if (subRecordCount == 5) {
            int a = 1;
          }
          Object o = subRecordArray.get(subRecordCount);
          if (o == null)
            break;
          subRecordCount++;
          if (o instanceof UnknownHProfRecord) {
            break;
          }
        }

      }
      return subRecordCount;
    }

    @Override
    public long getDataLength() {
      return (int) size;
    }

    @Override
    public byte[] getData() {
      try {
        return peek(myP, 20);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return null;
    }

    @Override
    public long getSubRecordLocation(int index) {
      return subRecordArray.getLocation(index);
    }

    @Override
    /**
     * Return a record by its locations
     *
     * @param location
     * @return IHProfRecord at given location
     */
    public IHProfRecord getSubRecordByLocation(long location) {   
      return (IHProfRecord) subRecordArray.getAtLocation(location);
    }
  }

  private final class HProfDumpRecordArrayProvider extends
      DataProviderBackedArrayProvider {
    private HProfDumpRecordArrayProvider(IDataProvider provider) {
      super(provider);
    }

    private IHProfRecord buildClassDumpRecord(int tag,
        IDataProvider dumpRecordProvider) throws IOException {

      long loc = dumpRecordProvider.getCurrentLocation();
      dumpRecordProvider.moveBy((idSize * 7) + 8);
      short elements = dumpRecordProvider.readU2(); // size of constant
      // pool
      int constantPoolIndex = (int)(dumpRecordProvider.getCurrentLocation()
          - loc);
      for (int i = 0; i < elements; i++) {
        short cpIndex = dumpRecordProvider.readU2();
        short type = dumpRecordProvider.readByte();
        int arrayLength = sizes.getLengthFromType(type);
        dumpRecordProvider.moveBy(arrayLength);
      }

      short staticFields = dumpRecordProvider.readU2();
           
      int staticFieldsIndex = (int)(dumpRecordProvider.getCurrentLocation()- loc);
      for (int i = 0; i < staticFields; i++) {
        long index = DataReader.readNumber(dumpRecordProvider, idSize);
        short type = dumpRecordProvider.readByte();
        int arrayLength = sizes.getLengthFromType(type);
        dumpRecordProvider.moveBy(arrayLength);
      }

      short instFields = dumpRecordProvider.readU2();

      int instFieldsIndex = (int) (dumpRecordProvider.getCurrentLocation()- loc);
      for (int i = 0; i < instFields; i++) {
        long index = DataReader.readNumber(dumpRecordProvider, idSize);
        short type = dumpRecordProvider.readByte();
      }

      long datalength = dumpRecordProvider.getCurrentLocation() - loc;
      SubsetDataProvider p = new SubsetDataProvider(dumpRecordProvider,
          loc, datalength);

      // Pass indices of static and instance fields - they are variable length.
      return new GCClassHeapDumpRecord((byte) tag, p, staticFieldsIndex, instFieldsIndex );

    }

    @Override
    public Object getCurrentElement() {
      // read tag
      try {
        long l = getProvider().getCurrentLocation();

        IDataProvider p = getProvider();
        if (p.dataRemaining() < 1)
          return null;
        short tag = p.readByte();
        int size = getRecordSize(tag);
        byte[] data = null;
        if (size >= 0) {
          data = getProvider().readBytes(size);
        }

        switch (tag) {
        case 0xFF: // unknown root
          return new GCRootUnknownHeapRecord(tag, data);

        case 0x01: // jni global root

          return new GCRootJNIGlobalRefHeapRecord(tag, data);

        case 0x02: // jni local
          return new GCRootJNILocalHeapRecord(tag, data);

        case 0x03: // java frame
          return new GCRootJavaFrameHeapRecord(tag, data);

        case 0x04: // native stack root
          return new GCRootNativeStackHeapRecord(tag, data);

        case 0x05: // stick class root
          return new GCRootStickyClassHeapRecord(tag, data);

        case 0x06: // thread block root
          return new GCRoothreadBlockHeapRecord(tag, data);

        case 0x07: // monitor used
          return new GCRootMonitorUsedHeapRecord(tag, data);

        case 0x08: // thread obj root
          return new GCRootThreadObjHeapRecord(tag, data);

        case 0x20: // class dump
          return buildClassDumpRecord(tag, getProvider());
        case 0x21: // instance
          return buildInstanceDumpRecord(tag, getProvider());

        case 0x22: // obj array
          return buildObjArrayDumpRecord(tag, getProvider());
        case 0x23: // primitive array
          return buildPrimitiveArrayDumpRecord(tag, getProvider());

        default:
          // don't know what this is
          return new UnknownHProfRecord(tag, null);

        }

      } catch (IOException e) {
        e.printStackTrace();
        return null;
      }

    }

    private Object buildPrimitiveArrayDumpRecord(short tag,
        IDataProvider arrayProvider) throws IOException {

      long loc = arrayProvider.getCurrentLocation();
      arrayProvider.moveBy(idSize + 4);
      int elements = arrayProvider.readU4();
      short elementType = arrayProvider.readByte();

      int elementLength = sizes.getLengthFromType(elementType);
      int datalength = idSize + 9 + (elementLength * elements);
      arrayProvider.moveTo(loc);
      SubsetDataProvider p = new SubsetDataProvider(arrayProvider,
          datalength);
      arrayProvider.moveTo(loc + datalength);
      return new GCPrimitiveArrayHeapDumpRecord(tag, p);
    }

    /**
     *
     * id array object ID u4 stack trace serial number u4 number of elements
     * id array class ID [id]* elements
     *
     * @param tag
     * @param arrayProvider
     * @return
     * @throws IOException
     */
    private Object buildObjArrayDumpRecord(short tag,
        IDataProvider arrayProvider) throws IOException {

      long loc = arrayProvider.getCurrentLocation();
      arrayProvider.moveBy(idSize + 4);
      int elements = arrayProvider.readU4();
      int datalength = (idSize * 2) + 8 + (idSize * elements);
      arrayProvider.moveTo(loc);
      SubsetDataProvider p = new SubsetDataProvider(arrayProvider,
          datalength);
      arrayProvider.moveTo(loc + datalength);
      return new GCObjectArrayHeapDumpRecord(tag, p);
    }

    /**
     * id object ID u4 stack trace serial number id class object ID u4
     * number of bytes that follow [vl]* instance field values (class,
     * followed by super, super's super ...)
     *
     * @param tag
     * @param arrayProvider
     * @return
     * @throws IOException
     */
    private Object buildInstanceDumpRecord(short tag,
        IDataProvider arrayProvider) throws IOException {

      long loc = arrayProvider.getCurrentLocation();
      arrayProvider.moveBy((idSize * 2) + 4);
      int byteCount = arrayProvider.readU4();
      int datalength = (idSize * 2) + 8 + byteCount;
      arrayProvider.moveTo(loc);
      SubsetDataProvider p = new SubsetDataProvider(arrayProvider,
          datalength);
      arrayProvider.moveTo(loc + datalength);
      return new GCInstanceHeapDumpRecord(tag, p);
    }

    /**
     * Returns record size for given tag.
     *
     * @param tag -
     *            tag to size
     * @return record size or -1 if dynamic, -2 if unknown tag
     */
    private int getRecordSize(int tag) {
      int recordLength = 0;

      switch (tag) {

      case 0xFF: // unknown root

        recordLength = idSize;
        break;

      case 0x01: // jni global root

        recordLength = idSize * 2;
        break;

      case 0x02: // jni local
        recordLength = idSize + 8;
        break;

      case 0x03: // java frame
        recordLength = idSize + 8;
        break;

      case 0x04: // native stack root
        recordLength = idSize + 4;
        break;

      case 0x05: // stick class root
        recordLength = idSize;
        break;

      case 0x06: // thread block root
        recordLength = idSize + 4;
        break;

      case 0x07: // monitor used
        recordLength = idSize;
        break;

      case 0x08: // thread obj root
        recordLength = idSize + 8;
        break;

      case 0x20: // class dump
      case 0x21: // instance
      case 0x22: // obj array
      case 0x23: // primitive array
        recordLength = -1;
        break;
      default:
        // don't know what this is
        recordLength = -2;

      }
      return recordLength;
    }
  }

  private final class HPROFRecordProvider implements IArrayEntryProvider {

    private IDataProvider recordProvider = null;

    public HPROFRecordProvider(IDataProvider provider) {
      this.recordProvider = provider;
    }

    @Override
    public IHProfRecord getCurrentElement() {

      // read tag
      try {

        short tag = recordProvider.readByte();
        int ms = recordProvider.readU4();
        int left = recordProvider.readU4();
        byte[] data = null;

        switch (tag) {
        case 0x0c:
          break;
        default:

          data = recordProvider.readBytes(left);

        }

        switch (tag) {

        case 0x01:

          return new UTF8HProfRecordImpl(tag, data);
        case 0x02:
          return new LoadClassHProfRecord(tag, data);
        case 0x03:
          return new UnloadClassHProfRecord(tag, data);
        case 0x04:
          return new FrameHProfRecord(tag, data);
        case 0x05:
          return new TraceHProfRecord(tag, data);
        case 0x0e:
          return new ControlSettingsHProfRecord(tag, data);

        case 0x0a:
          return new StartThreadHProfRecord(tag, data);
        case 0x0b:
          return new EndThreadHProfRecord(tag, data);

        case 0x0c:
          IHeapDumpHProfRecord rec = new HeapDumpHProfRecord(tag,
              new SubsetDataProvider(recordProvider, left));
          recordProvider.moveBy(left);
          return rec;
        default:
          // don't know what the thing is - return an unknown
          // type.

          return new UnknownHProfRecord(tag, data);
        }

      } catch (IOException e) {
        return null;
      }

    }

    @Override
    public long getCurrentLocation() {

      try {
        return recordProvider.getCurrentLocation();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return -1;
    }

    @Override
    public void getState(List state) {

      state.add("HProfRecordProvider");
      recordProvider.addState(state);

    }

    @Override
    public boolean moveRelativeElement(int seekNo) {

      while (seekNo > 0) {
        Object o = getCurrentElement();
        if (o == null)
          return false;
        seekNo--;
      }
      return true;
    }

    @Override
    public boolean moveToLocation(long l) {

      try {
        recordProvider.moveTo(l);
        return true;
      } catch (IOException e) {
        return false;
      }
    }
  }

  class LoadClassHProfRecord extends HProfRecord implements
      ILoadClassHProfRecord {

    public LoadClassHProfRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public long getClassNameID() {
      return readNumber(8 + idSize, idSize);
    }

    public long getClassObjectID() {
      return readNumber(4, idSize);
    }

    public int getClassSerialNumber() {
      return readInt(0);
    }

    public int getStackTraceSerialNumber() {
      return readInt(4 + idSize);
    }
  }

  class UnloadClassHProfRecord extends HProfRecord implements
      IUnloadClassHProfRecord {

    public UnloadClassHProfRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public int getClassSerialNumber() {
      return readInt(0);
    }
  }

  class StartThreadHProfRecord extends HProfRecord implements
      IThreadActiveHProfRecord {

    public StartThreadHProfRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public int getStackTraceSerialNumber() {
      return readInt(idSize + 4);
    }

    public long getThreadGroupNameID() {
      return readNumber(8 + (idSize * 2), idSize);

    }

    public long getThreadGroupParentNameID() {
      return readNumber(8 + (idSize * 3), idSize);
    }

    public long getThreadNameID() {
      return readNumber(8 + idSize, idSize);
    }

    public long getThreadObjectID() {
      return readNumber(4, idSize);
    }

    public int getThreadSerialNumber() {
      return readInt(0);
    }
  }

  class TraceHProfRecord extends HProfRecord implements
      IJavaStackTraceHProfRecord {

    public TraceHProfRecord(short tag, byte[] data) {
      super(tag, data);
    }

    public int getFrameCount() {
      return readInt(8);
    }

    public int getSerialNumber() {
      return readInt(0);
    }

    public long getStackFrameID(int elementNo) {
      return readNumber((idSize * elementNo) + 12, idSize);
    }

    public int getThreadSerialNumber() {
      return readInt(4);
    }
  }

  class UnknownHProfRecord extends HProfRecord {

    public UnknownHProfRecord(short tag, byte[] data) {
      super(tag, data);

    }

  }

  class UTF8HProfRecordImpl extends HProfRecord implements IUTF8HProfRecord {

    public UTF8HProfRecordImpl(short tag, byte[] data) {
      super(tag, data);

    }

    @Override
    public String getAsString() {

      try {
        return new String(getCharacters(), "UTF-8");
      } catch (UnsupportedEncodingException e) {

        return null;
      }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.kato.hprof.IUTF8HProfRecord#getCharacters()
     */
    public byte[] getCharacters() {

      int length = ((int) getDataLength()) - idSize;
      return readBytes(idSize, length);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.kato.hprof.IUTF8HProfRecord#getNameID()
     */
    public long getNameID() {
      return readNumber(0, idSize);
    }
  }

  private BitMaskMappingArray array = null;

  private String header = null;

  private Integer idSize = null;
  private HProfDataTypeSizes sizes = null;

  private IDataProvider mainProvider = null;

  private int records = -1;
  private long recordsOffset = 0;

  private Long timeStamp = null;

  private File source=null;
 
  public HProfFile(IDataProvider provider) {
    this.mainProvider = provider;
  }

  public byte[] peek(IDataProvider dumpRecordProvider, int i)
      throws IOException {
    long loc = dumpRecordProvider.getCurrentLocation();
    long bytesLeft = dumpRecordProvider.getDataLength()
        - dumpRecordProvider.getCurrentLocation();
    if (i > bytesLeft)
      i = (int) bytesLeft;
    byte[] b = dumpRecordProvider.readBytes(i);
    dumpRecordProvider.moveTo(loc);
    return b;
  }

  private void buildHeader() throws IOException {

    try {
      header = mainProvider.readCString();
    } catch (IOException ioe) {
      throw new InvalidFileFormat("File is not an HPROF file", ioe);
    }
    if (header.equals("JAVA PROFILE 1.0.1") == false
        && header.equals("JAVA PROFILE 1.0.2") == false) {
      throw new InvalidFileFormat("File is not an HPROF file");
    }
    try {
      idSize = mainProvider.readU4();
      timeStamp = mainProvider.readU8();
    } catch (IOException ioe) {
      throw new InvalidFileFormat("HPROF file is truncated", ioe);
    }
    sizes = new HProfDataTypeSizes(idSize);

    recordsOffset = mainProvider.getCurrentLocation();
    long maxOffsetLength = mainProvider.getDataLength() - recordsOffset;
    SubsetDataProvider subset = new SubsetDataProvider(mainProvider,
        maxOffsetLength);
    array = new BitMaskMappingArray(1000, 25, new HPROFRecordProvider(
        subset));

  }

  public void close() throws IOException {
    mainProvider.close();

  }

  public String getHeader() {

    return header;
  }

  public Integer getIdentifierSize() {

    return idSize;
  }

  public long getRecordLocation(int index) {
    if (index < 0)
      throw new IllegalArgumentException("record index [" + index
          + "] is less than zero");
    return array.getLocation(index) + recordsOffset + 9; // add 9 for
    // header bytes
    // of heap dump
    // record
  }

  public IHProfRecord getRecord(int index) {

    if (index < 0)
      throw new IllegalArgumentException("record index [" + index
          + "] is less than zero");
    return (IHProfRecord) array.get(index);
  }

  public int getRecordCount() {

    if (records < 0)
      records = readRecords();
    return records;
  }

  public Long getTimeStamp() {
    return timeStamp;
  }

  public void open() throws IOException {
    mainProvider.open();
    buildHeader();
  }

  private int readRecords() {
    int counter = 0;
    IHProfRecord record = null;

    while (true) {
      record = getRecord(counter);
      if (record == null)
        break;
      counter++;

    }
    return counter;
  }

  class GCRoothreadBlockHeapRecord extends HProfRecord {

    public GCRoothreadBlockHeapRecord(short tag, byte[] data) {
      super(tag, data);
    }

    public long getId() {
      return readNumber(0, idSize);
    }

    public int getThreadSerialNumber() {
      return readInt(idSize);
    }

  }

  class GCRootJavaFrameHeapRecord extends HProfRecord {

    public GCRootJavaFrameHeapRecord(short tag, byte[] data) {
      super(tag, data);
    }

    public long getId() {
      return readNumber(0, idSize);
    }

    public int getThreadSerialNumber() {
      return readInt(idSize);
    }

    public int getStackFrameNumber() {
      return readInt(idSize + 4);
    }

  }

  class GCRootJNIGlobalRefHeapRecord extends HProfRecord {

    public GCRootJNIGlobalRefHeapRecord(short tag, byte[] data) {
      super(tag, data);
    }

    public long getObjid() {
      return readNumber(0, idSize);
    }

    public long getJniid() {
      return readNumber(idSize, idSize);
    }

  }

  class GCRootJNILocalHeapRecord extends HProfRecord {

    public GCRootJNILocalHeapRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public long getId() {
      return readNumber(0, idSize);
    }

    public int getThreadSerialNumber() {
      return readInt(idSize);
    }

    public int getStackFrameNumber() {
      return readInt(idSize + 4);
    }

  }

  public abstract class IDEntryHeapRecord extends HProfRecord {

    public IDEntryHeapRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public long getID() {
      return readNumber(0, idSize);
    }
  }

  class GCRootMonitorUsedHeapRecord extends IDEntryHeapRecord {

    public GCRootMonitorUsedHeapRecord(short tag, byte[] data) {
      super(tag, data);

    }

  }

  class GCRootStickyClassHeapRecord extends IDEntryHeapRecord {

    public GCRootStickyClassHeapRecord(short tag, byte[] data) {
      super(tag, data);

    }

  }

  class GCRootUnknownHeapRecord extends HProfRecord {

    public GCRootUnknownHeapRecord(short tag, byte[] data) {
      super(tag, data);

    }

  }

  class GCRootThreadObjHeapRecord extends HProfRecord {

    public GCRootThreadObjHeapRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public long getId() {
      return readNumber(0, idSize);
    }

    public int getThreadSequenceNumber() {
      return readInt(idSize);
    }

    public int getStackTraceSequenceNumber() {
      return readInt(idSize + 4);
    }

  }

  class GCRootNativeStackHeapRecord extends HProfRecord {

    public GCRootNativeStackHeapRecord(short tag, byte[] data) {
      super(tag, data);

    }

    public long getId() {
      return readNumber(0, idSize);
    }

    public int getThreadSequenceNumber() {
      return readInt(idSize);
    }

  }

  abstract class LightHeapEntryRecord implements IHProfRecord {

    private IDataProvider lightProvider = null;
    private short tag = 0;

    public LightHeapEntryRecord(short tag, IDataProvider provider) {
      this.tag = tag;
      this.lightProvider = provider;
    }

    @Override
    public byte[] getData() {
      try {
        return peek(lightProvider, (int)Math.min(200, this.getDataLength()));
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return null;
    }

    public short getTag() {
      return tag;
    }

    public long getDataLength() {

      try {
        return lightProvider.getDataLength();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return -1;
    }

    public IDataProvider getProvider() {
      return lightProvider;
    }

    protected long readLong(int offset) {     
      try {
        lightProvider.moveTo(offset);
        return lightProvider.readU8();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return -1;

    }

    protected int readInt(int offset) {
      try {
        lightProvider.moveTo(offset);
        return lightProvider.readU4();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return -1;

    }

    protected short readByte(int offset) {
      try {
        lightProvider.moveTo(offset);
        return lightProvider.readByte();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return -1;

    }

    protected char readChar(int offset) {
      try {
        lightProvider.moveTo(offset);
        return (char)lightProvider.readU2();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return (char)-1;

    }
   
    protected short readShort(int offset) {
      try {
        lightProvider.moveTo(offset);
        return lightProvider.readU2();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return -1;
    }

    protected long readNumber(int offset, int length) {
      try {
        lightProvider.moveTo(offset);
        return DataReader.readNumber(lightProvider, length);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return -1;

    }

    protected byte[] readBytes(int offset, int length) {
      try {
        lightProvider.moveTo(offset);
        return lightProvider.readBytes(length);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      return null;
    }
   
    @Override
    public String toString() {
      StringBuffer output = new StringBuffer("LightHeapRecord: Tag: 0x");
      output.append(Long.toHexString(getTag()));
      output.append(", length:");
      output.append(getDataLength());
      output.append(", Data:");
      for (int i=0; i < getDataLength(); i++) {
        short val = (short) (((short)readByte(i))&0xff);
        if (val <= 0xf) {
          output.append('0');
        }
        output.append(Integer.toHexString(val));
      }
     
      return output.toString();
    }
  }

  class GCPrimitiveArrayHeapDumpRecord extends LightHeapEntryRecord  implements IGCPrimitiveArrayHeapDumpRecord {

    public GCPrimitiveArrayHeapDumpRecord(short tag, IDataProvider provider) {
      super(tag, provider);

    }

    @Override
    public long getID() {
      return readNumber(0, idSize);
    }

    @Override
    public int getStackTraceNumber() {
      return readInt(idSize);
    }

    @Override
    public int getNumberOfElements() {
      return readInt(idSize + 4);
    }

    @Override
    public short getElementType() {
      return readByte(idSize + 8);
    }

    @Override
    public boolean getBooleanElement(int index) {
      return getByteElement(index) != 0;
    }
   
    @Override
    public short getByteElement(int index) {
      return readByte(idSize+9+index);
    }
   
    @Override
    public short getShortElement(int index) {
      return readShort(idSize+ 9 + index * 2);
    }
   
    @Override
    public char getCharElement(int index) {
      return readChar(idSize+ 9 + index * 2);
    }
   
    @Override
    public int getIntElement(int index) {
      return readInt(idSize+ 9 + index * 4);
    }
   
    @Override
    public long getLongElement(int index) {
      return readLong(idSize+ 9 + index * 8);
    }
   
    @Override
    public float getFloatElement(int index) {
      return Float.intBitsToFloat(getIntElement(index));
    }
   
    @Override
    public double getDoubleElement(int index) {
      long lval =getLongElement(index);
       
      return Double.longBitsToDouble(lval);
    }
  }

  /**
   * An array of references on the heap.
   *
   */
  class GCObjectArrayHeapDumpRecord extends LightHeapEntryRecord implements IGCObjectArrayHeapDumpRecord {

    public GCObjectArrayHeapDumpRecord(short tag, IDataProvider provider) {
      super(tag, provider);

    }

    @Override
    public long getID() {
      return readNumber(0, idSize);
    }

    @Override
    public int getStackTraceNumber() {
      return readInt(idSize);
    }

    @Override
    public int getNumberOfElements() {
      return readInt(idSize + 4);
    }

    @Override
    public long getArrayClassObjectID() {
      return readNumber(idSize + 8, idSize);
    }
   
    @Override
    public long getElement(int index) {
      return readNumber(idSize*2+8 + index * idSize, idSize);
    }


    @Override
    public String toString() {
      StringBuffer output = new StringBuffer(super.toString());
      output.append("\nReferences: ");
      for (int i=0; i < getNumberOfElements(); i++) {
        output.append("0x").append(Long.toHexString(getElement(i))).append(' ');
      }
     
      return output.toString();
    }
  }

  /**
   * An ordinary object instance on the heap.
   *
   */
  class GCInstanceHeapDumpRecord extends LightHeapEntryRecord implements IGCInstanceHeapDumpRecord {

    public GCInstanceHeapDumpRecord(short tag, IDataProvider provider) {
      super(tag, provider);

    }

    public long getID() {
      return readNumber(0, idSize);
    }

    public int getStackTraceNumber() {
      return readInt(idSize);
    }

    public long getClassObjectID() {
      return readNumber(idSize + 4, idSize);
    }

    public int getNumberOfValueBytes() {
      return readInt((idSize * 2) + 4);
    }

    @Override
    public byte getByteField(int offset) {
      return (byte) readByte((idSize*2 + 8) + offset);
    }

    @Override
    public char getCharField(int offset) {
      return readChar((idSize*2 + 8) + offset);
    }

    @Override
    public double getDoubleField(int offset) {
      long lval = readLong((idSize*2 + 8) + offset);
     
      //lval = (( 0x00000000ffffffffl & lval) << 32) | (((0xffffffff00000000l) & lval) >>>32);

      return Double.longBitsToDouble(lval);
    }

    @Override
    public float getFloatField(int offset) {
      return Float.intBitsToFloat(readInt((idSize*2 + 8) + offset));
    }

    @Override
    public long getIDField(int offset) {   
      return readNumber((idSize*2 + 8) + offset,idSize);
    }

    @Override
    public int getIntegerField(int offset) {
      return readInt((idSize*2 + 8) + offset);
    }

    @Override
    public long getLongField(int offset) { 
      return readLong((idSize*2 + 8) + offset);
    }

    @Override
    public short getShortField(int offset) {
      return readShort((idSize*2 + 8) + offset);
    }

    @Override
    public boolean getBooleanField(int offset) {
      return !(getByteField(offset) == 0);
    }

  }

  public class GCClassHeapDumpRecord extends LightHeapEntryRecord implements IGCClassHeapDumpRecord, IHeapObject {

    private int staticFieldsOffset;
    private int instFieldsOffset;

    public GCClassHeapDumpRecord(byte tag, IDataProvider provider
        , int staticFieldsOffset, int instFieldsOffset ) {
      super(tag, provider);
     
      this.staticFieldsOffset = staticFieldsOffset;
      this.instFieldsOffset = instFieldsOffset;
    }

    public long getID() {
      return readNumber(0, idSize);
    }

    public int getStackTraceNumber() {
      return readInt(idSize);
    }

    public long getSuperClassObjectID() {
      return readNumber(idSize + 4, idSize);
    }

    public long getClassLoaderObjectID() {
      return readNumber((idSize * 2) + 4, idSize);
    }

    public long getSignersObjectID() {
      return readNumber((idSize * 3) + 4, idSize);
    }

    public long getProtectionDomainObjectID() {
      return readNumber((idSize * 4) + 4, idSize);
    }

    public int getInstanceSize() {
      return readInt((idSize * 7) + 4);
    }

    public int getConstantPoolSize() {
      return readShort((idSize * 7) + 8);
    }

    public ConstantPoolEntry[] getConstantPool() {
      return readConstantPool((idSize * 7) + 10);
    }

    private ConstantPoolEntry[] readConstantPool(int offset) {
      int entries = getConstantPoolSize();
      ConstantPoolEntry[] pool = new ConstantPoolEntry[entries];
      for (int i = 0; i < entries; i++) {
        ConstantPoolEntry cpe = new ConstantPoolEntry();
        cpe.cpIndex = readShort(offset);
        offset += 2;
        cpe.type = readByte(offset);
        offset++;
        int valueLength = sizes.getLengthFromType(cpe.type);
        cpe.data = readBytes(offset, valueLength);
        offset += valueLength;
        pool[i] = cpe;
      }
      return pool;
    }

    public StaticFieldEntry[] getStaticFields() {
      return readStaticFields(staticFieldsOffset);     
    }
   
    private StaticFieldEntry[] readStaticFields(int offset) {
      short staticFields = readShort(offset-2);
     
      StaticFieldEntry[] fields = new StaticFieldEntry[staticFields];
      for (int i = 0; i < staticFields; i++) {
        long stringID = readNumber(offset,idSize);
        offset += idSize;
        short type = readByte(offset);
        offset+=1;
        int arrayLength = sizes.getLengthFromType(type);
        long data = readNumber(offset, arrayLength);
        offset += arrayLength;
       
        fields[i] = new StaticFieldEntry(stringID, type, data);
      }
     
      return fields;
    }
   
    public InstanceFieldEntry[] getInstanceFields() {
      return readInstanceFields(instFieldsOffset);
    }

    private InstanceFieldEntry[] readInstanceFields(int offset) {
      short instFields = readShort(offset-2);
      int fieldOffset = 0;
      InstanceFieldEntry[] fields = new InstanceFieldEntry[instFields];
     
      for (int i = 0; i < instFields; i++) {
        long stringID = readNumber(offset,idSize);
        offset += idSize;
       
        short type = readByte(offset);
        offset+=1;
               
        fields[i] = new InstanceFieldEntry(stringID, type, fieldOffset);
        fieldOffset += sizes.getLengthFromType(type);
      }
      offsetSize = fieldOffset;
      return fields;
    }

    private int offsetSize=-1;
    @Override
    public int getOffsetSize() {
      if(offsetSize == -1) {
        getInstanceFields();
      }
      return offsetSize;
    }
   
  }

  public void setSource(File source) {
    this.source=source;
   
  }

  public File getSource() {
    return source;
  }
}
TOP

Related Classes of org.apache.kato.hprof.datalayer.HProfFile$UnloadClassHProfRecord

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.