org.eclipse.mat.hprof.HprofHeapObjectReader Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2008 SAP AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.mat.hprof;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.mat.SnapshotException;
import org.eclipse.mat.hprof.extension.IRuntimeEnhancer;
import org.eclipse.mat.parser.IObjectReader;
import org.eclipse.mat.parser.index.IIndexReader;
import org.eclipse.mat.parser.index.IndexReader;
import org.eclipse.mat.parser.model.AbstractArrayImpl;
import org.eclipse.mat.parser.model.ObjectArrayImpl;
import org.eclipse.mat.parser.model.PrimitiveArrayImpl;
import org.eclipse.mat.snapshot.ISnapshot;
import org.eclipse.mat.snapshot.model.IObject;
import org.eclipse.mat.snapshot.model.IPrimitiveArray;
public class HprofHeapObjectReader implements IObjectReader {
public static final String VERSION_PROPERTY = "hprof.version"; //$NON-NLS-1$
private ISnapshot snapshot;
private HprofRandomAccessParser hprofDump;
private IIndexReader.IOne2LongIndex o2hprof;
private List enhancers;
public void open(ISnapshot snapshot) throws IOException {
this.snapshot = snapshot;
AbstractParser.Version version = AbstractParser.Version.valueOf((String) snapshot.getSnapshotInfo()
.getProperty(VERSION_PROPERTY));
this.hprofDump = new HprofRandomAccessParser(new File(snapshot.getSnapshotInfo().getPath()), //
version, //
snapshot.getSnapshotInfo().getIdentifierSize());
this.o2hprof = new IndexReader.LongIndexReader(new File(snapshot.getSnapshotInfo().getPrefix()
+ "o2hprof.index")); //$NON-NLS-1$
this.enhancers = new ArrayList();
// There is no ehancers so far.
// for (EnhancerRegistry.Enhancer enhancer : EnhancerRegistry.instance().delegates())
// {
// IRuntimeEnhancer runtime = enhancer.runtime();
// if (runtime != null)
// this.enhancers.add(runtime);
// }
}
public long[] readObjectArrayContent(ObjectArrayImpl array, int offset, int length) throws IOException,
SnapshotException {
Object info = array.getInfo();
if (info instanceof ArrayDescription.Offline) {
ArrayDescription.Offline description = (ArrayDescription.Offline) info;
long[] answer = (long[]) description.getLazyReadContent();
if (answer == null) {
answer = hprofDump.readObjectArray(description, offset, length);
// save content if fully read...
if (offset == 0 && length == array.getLength())
description.setLazyReadContent(answer);
return answer;
} else {
return (long[]) fragment(array, answer, offset, length);
}
} else if (info instanceof long[]) {
return (long[]) fragment(array, info, offset, length);
} else {
throw new IllegalArgumentException();
}
}
public Object readPrimitiveArrayContent(PrimitiveArrayImpl array, int offset, int length) throws IOException,
SnapshotException {
Object info = array.getInfo();
if (info instanceof ArrayDescription.Offline) {
ArrayDescription.Offline description = (ArrayDescription.Offline) info;
Object content = description.getLazyReadContent();
if (content == null) {
content = convert(array, hprofDump.readPrimitiveArray(description, offset, length));
// save content if fully read...
if (offset == 0 && length == array.getLength())
description.setLazyReadContent(content);
return content;
} else {
return fragment(array, content, offset, length);
}
} else if (info instanceof ArrayDescription.Raw) {
ArrayDescription.Raw description = (ArrayDescription.Raw) info;
Object content = convert(array, description.getContent());
array.setInfo(content);
return fragment(array, content, offset, length);
} else {
return fragment(array, info, offset, length);
}
}
private Object convert(PrimitiveArrayImpl array, byte[] content) {
if (array.getType() == IObject.Type.BYTE)
return content;
int elementSize = IPrimitiveArray.ELEMENT_SIZE[array.getType()];
int length = content.length / elementSize;
Object answer = Array.newInstance(IPrimitiveArray.COMPONENT_TYPE[array.getType()], length);
int index = 0;
for (int ii = 0; ii < content.length; ii += elementSize) {
switch (array.getType()) {
case IObject.Type.BOOLEAN:
Array.set(answer, index, content[ii] != 0);
break;
case IObject.Type.CHAR:
Array.set(answer, index, readChar(content, ii));
break;
case IObject.Type.FLOAT:
Array.set(answer, index, readFloat(content, ii));
break;
case IObject.Type.DOUBLE:
Array.set(answer, index, readDouble(content, ii));
break;
case IObject.Type.SHORT:
Array.set(answer, index, readShort(content, ii));
break;
case IObject.Type.INT:
Array.set(answer, index, readInt(content, ii));
break;
case IObject.Type.LONG:
Array.set(answer, index, readLong(content, ii));
break;
}
index++;
}
return answer;
}
private Object fragment(AbstractArrayImpl array, Object content, int offset, int length) {
if (offset == 0 && length == array.getLength())
return content;
Object answer = Array.newInstance(content.getClass().getComponentType(), length);
System.arraycopy(content, offset, answer, 0, length);
return answer;
}
public IObject read(int objectId, ISnapshot snapshot) throws SnapshotException, IOException {
long filePosition = o2hprof.get(objectId);
return hprofDump.read(objectId, filePosition, snapshot);
}
public A getAddon(Class addon) throws SnapshotException {
for (IRuntimeEnhancer enhancer : enhancers) {
A answer = enhancer.getAddon(snapshot, addon);
if (answer != null)
return answer;
}
return null;
}
public void close() throws IOException {
try {
hprofDump.close();
} catch (IOException ignore) {
}
try {
o2hprof.close();
} catch (IOException ignore) {
}
}
// //////////////////////////////////////////////////////////////
// conversion routines
// //////////////////////////////////////////////////////////////
private short readShort(byte[] data, int offset) {
int b1 = (data[offset] & 0xff);
int b2 = (data[offset + 1] & 0xff);
return (short) ((b1 << 8) + b2);
}
private char readChar(byte[] data, int offset) {
int b1 = (data[offset] & 0xff);
int b2 = (data[offset + 1] & 0xff);
return (char) ((b1 << 8) + b2);
}
private int readInt(byte[] data, int offset) {
int ch1 = data[offset] & 0xff;
int ch2 = data[offset + 1] & 0xff;
int ch3 = data[offset + 2] & 0xff;
int ch4 = data[offset + 3] & 0xff;
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
private float readFloat(byte[] data, int offset) {
return Float.intBitsToFloat(readInt(data, offset));
}
private long readLong(byte[] data, int offset) {
return ((((long) data[offset] & 0xff) << 56) + //
((long) (data[offset + 1] & 0xff) << 48) + //
((long) (data[offset + 2] & 0xff) << 40) + //
((long) (data[offset + 3] & 0xff) << 32) + //
((long) (data[offset + 4] & 0xff) << 24) + //
((data[offset + 5] & 0xff) << 16) + //
((data[offset + 6] & 0xff) << 8) + //
((data[offset + 7] & 0xff) << 0));
}
private double readDouble(byte[] data, int offset) {
return Double.longBitsToDouble(readLong(data, offset));
}
}