Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright 2014 Alexey Ragozin
*
* 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.gridkit.jvmtool.heapdump;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.gridkit.jvmtool.heapdump.PathStep.Move;
import org.netbeans.lib.profiler.heap.Field;
import org.netbeans.lib.profiler.heap.FieldValue;
import org.netbeans.lib.profiler.heap.Instance;
import org.netbeans.lib.profiler.heap.JavaClass;
import org.netbeans.lib.profiler.heap.ObjectFieldValue;
import org.netbeans.lib.profiler.heap.PrimitiveArrayInstance;
public class HeapWalker {
private static final Set BOX_TYPES = new HashSet();
static {
BOX_TYPES.add(Boolean.class.getName());
BOX_TYPES.add(Byte.class.getName());
BOX_TYPES.add(Short.class.getName());
BOX_TYPES.add(Character.class.getName());
BOX_TYPES.add(Integer.class.getName());
BOX_TYPES.add(Long.class.getName());
BOX_TYPES.add(Float.class.getName());
BOX_TYPES.add(Double.class.getName());
}
private static final Map CONVERTERS = new HashMap();
static {
CONVERTERS.put(String.class.getName(), new InstanceConverter() {
@Override
public Object convert(Instance instance) {
return stringValue(instance);
}
});
InstanceConverter primitiveConverter = new InstanceConverter() {
@Override
public Object convert(Instance instance) {
return primitiveValue(instance);
}
};
InstanceConverter primitiveArrayConverter = new InstanceConverter() {
@Override
public Object convert(Instance instance) {
return primitiveArrayValue(instance);
}
};
for(String ptype: BOX_TYPES) {
CONVERTERS.put(ptype, primitiveConverter);
}
CONVERTERS.put("boolean[]", primitiveArrayConverter);
CONVERTERS.put("byte[]", primitiveArrayConverter);
CONVERTERS.put("char[]", primitiveArrayConverter);
CONVERTERS.put("short[]", primitiveArrayConverter);
CONVERTERS.put("int[]", primitiveArrayConverter);
CONVERTERS.put("long[]", primitiveArrayConverter);
CONVERTERS.put("float[]", primitiveArrayConverter);
CONVERTERS.put("double[]", primitiveArrayConverter);
}
private static PrimitiveParser BOOL_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return Boolean.valueOf(x);
}
};
private static PrimitiveParser BYTE_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return Byte.valueOf(x);
}
};
private static PrimitiveParser SHORT_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return Short.valueOf(x);
}
};
private static PrimitiveParser CHAR_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return x.charAt(0);
}
};
private static PrimitiveParser INT_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return Integer.valueOf(x);
}
};
private static PrimitiveParser LONG_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return Long.valueOf(x);
}
};
private static PrimitiveParser FLOAT_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return Float.valueOf(x);
}
};
private static PrimitiveParser DOUBLE_PARSER = new PrimitiveParser() {
@Override
public Object toValue(String x) {
return Double.valueOf(x);
}
};
/**
* Converts instances of few well know Java classes from
* dump to normal java objects.
*
* Following are supported classes
*
{@link String}
*
{@link Boolean}
*
{@link Byte}
*
{@link Short}
*
{@link Character}
*
{@link Integer}
*
{@link Long}
*
{@link Float}
*
{@link Double}
*
primitive arrays
*
object arrays
*/
/* TBD
*
{@link Arrays#asList(Object...)}
*
{@link ArrayList} (subclasses would be reduced to {@link ArrayList})
*
{@link HashMap} (subclasses including {@link LinkedHashMap} would be reduced to {@link ArrayList})
*
{@link HashSet} (subclasses including {@link LinkedHashSet} would be reduced to {@link ArrayList})
*/
@SuppressWarnings("unchecked")
public static T valueOf(Instance obj) {
if (obj == null) {
return null;
}
JavaClass t = obj.getJavaClass();
InstanceConverter c = CONVERTERS.get(obj.getJavaClass().getName());
while(c == null && t.getSuperClass() != null) {
t = t.getSuperClass();
c = CONVERTERS.get(obj.getJavaClass().getName());
}
if (c == null) {
// return instance as is
return (T) obj;
}
else {
return (T)c.convert(obj);
}
}
/**
* Converts value referenced for path from dump to normal java objects.
* Few well known Java classes as long as primitive types are supported.
*
* Following are supported classes
*
{@link String}
*
{@link Boolean}
*
{@link Byte}
*
{@link Short}
*
{@link Character}
*
{@link Integer}
*
{@link Long}
*
{@link Float}
*
{@link Double}
*
primitive arrays
*
object arrays
*/
/* TBD
*
{@link Arrays#asList(Object...)}
*
{@link ArrayList} (subclasses would be reduced to {@link ArrayList})
*
{@link HashMap} (subclasses including {@link LinkedHashMap} would be reduced to {@link ArrayList})
*
{@link HashSet} (subclasses including {@link LinkedHashSet} would be reduced to {@link ArrayList})
*/
@SuppressWarnings("unchecked")
public static T valueOf(Instance obj, String pathSpec) {
PathStep[] steps = HeapPath.parsePath(pathSpec, true);
if (steps.length > 0 && steps[steps.length - 1] instanceof FieldStep) {
PathStep[] shortPath = Arrays.copyOf(steps, steps.length - 1);
FieldStep lastStep = (FieldStep) steps[steps.length - 1];
String fieldName = lastStep.getFieldName();
for(Instance i: HeapPath.collect(obj, shortPath)) {
for(FieldValue fv: i.getFieldValues()) {
if ((fieldName == null && (!fv.getField().isStatic()))
|| (fv.getField().getName().equals(fieldName))) {
if (fv instanceof ObjectFieldValue) {
return valueOf(((ObjectFieldValue) fv).getInstance());
}
else {
// have to use this as private package API is used behind scene
return (T) i.getValueOfField(fv.getField().getName());
}
}
}
}
return null;
}
else if (steps.length > 0 && steps[steps.length - 1] instanceof ArrayIndexStep) {
PathStep[] shortPath = Arrays.copyOf(steps, steps.length - 1);
ArrayIndexStep lastStep = (ArrayIndexStep) steps[steps.length - 1];
for(Instance i: HeapPath.collect(obj, shortPath)) {
if (i instanceof PrimitiveArrayInstance) {
Object array = valueOf(i);
if (array != null) {
int len = Array.getLength(array);
int n = lastStep.getIndex();
if (n < 0) {
n = 0;
}
if (n < len) {
return (T) Array.get(array, n);
}
else {
return null;
}
}
}
else {
for(Instance x: HeapPath.collect(i, new PathStep[]{lastStep})) {
return valueOf(x);
}
}
}
return null;
} else {
for(Instance i: HeapPath.collect(obj, steps)) {
return valueOf(i);
}
return null;
}
}
public static String stringValue(Instance obj) {
if (obj == null) {
return null;
}
if (!"java.lang.String".equals(obj.getJavaClass().getName())) {
throw new IllegalArgumentException("Is not a string: " + obj.getInstanceId() + " (" + obj.getJavaClass().getName() + ")");
}
char[] text = null;
int offset = 0;
int len = -1;
for(FieldValue f: obj.getFieldValues()) {
Field ff = f.getField();
if ("value".equals(ff.getName())) {
PrimitiveArrayInstance chars = (PrimitiveArrayInstance) ((ObjectFieldValue)f).getInstance();
text = new char[chars.getLength()];
for(int i = 0; i != text.length; ++i) {
text[i] = ((String)chars.getValues().get(i)).charAt(0);
}
}
// fields below were removed in Java 7
else if ("offset".equals(ff.getName())) {
offset = Integer.valueOf(f.getValue());
}
else if ("count".equals(ff.getName())) {
len = Integer.valueOf(f.getValue());
}
}
if (len < 0) {
len = text.length;
}
return new String(text, offset, len);
}
@SuppressWarnings("unchecked")
public static T primitiveValue(Instance obj) {
if (obj == null) {
return null;
}
String className = obj.getJavaClass().getName();
if (BOX_TYPES.contains(className)) {
return (T)obj.getValueOfField("value");
}
else {
throw new IllegalArgumentException("Is not a primitive wrapper: " + obj.getInstanceId() + " (" + obj.getJavaClass().getName() + ")");
}
}
@SuppressWarnings("unchecked")
public static T primitiveArrayValue(Instance obj) {
if (obj == null) {
return null;
}
if (obj instanceof PrimitiveArrayInstance) {
PrimitiveArrayInstance pa = (PrimitiveArrayInstance) obj;
String type = pa.getJavaClass().getName();
PrimitiveParser parser;
Object array;
int len = pa.getLength();
if ("boolean[]".equals(type)) {
array = new boolean[len];
parser = BOOL_PARSER;
}
else if ("byte[]".equals(type)) {
array = new byte[len];
parser = BYTE_PARSER;
}
else if ("char[]".equals(type)) {
array = new char[len];
parser = CHAR_PARSER;
}
else if ("short[]".equals(type)) {
array = new short[len];
parser = SHORT_PARSER;
}
else if ("int[]".equals(type)) {
array = new int[len];
parser = INT_PARSER;
}
else if ("long[]".equals(type)) {
array = new long[len];
parser = LONG_PARSER;
}
else if ("float[]".equals(type)) {
array = new float[len];
parser = FLOAT_PARSER;
}
else if ("double[]".equals(type)) {
array = new double[len];
parser = DOUBLE_PARSER;
}
else {
throw new IllegalArgumentException("Is not a primitive array: " + obj.getInstanceId() + " (" + obj.getJavaClass().getName() + ")");
}
List