java怎么算内存消耗_计算java对象的内存占用

importjava.lang.reflect.Array;importjava.lang.reflect.Field;importjava.lang.reflect.Modifier;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Collections;importjava.util.HashMap;importjava.util.IdentityHashMap;importjava.util.List;importjava.util.Map;importsun.misc.Unsafe;/*** This class could be used for any object contents/memory layout printing.*/

public classClassIntrospector {private static finalUnsafe unsafe;/**Size of any Object reference*/

private static final intobjectRefSize;static{try{

Field field= Unsafe.class.getDeclaredField("theUnsafe");

field.setAccessible(true);

unsafe= (Unsafe) field.get(null);

objectRefSize= unsafe.arrayIndexScale(Object[].class);

}catch(Exception e) {throw newRuntimeException(e);

}

}/**Sizes of all primitive values*/

private static final MapprimitiveSizes;static{

primitiveSizes= new HashMap(10);

primitiveSizes.put(byte.class, 1);

primitiveSizes.put(char.class, 2);

primitiveSizes.put(int.class, 4);

primitiveSizes.put(long.class, 8);

primitiveSizes.put(float.class, 4);

primitiveSizes.put(double.class, 8);

primitiveSizes.put(boolean.class, 1);

}/*** Get object information for any Java object. Do not pass primitives to

* this method because they will boxed and the information you will get will

* be related to a boxed version of your value.

*

*@paramobj

* Object to introspect

*@returnObject info

*@throwsIllegalAccessException*/

public ObjectInfo introspect(finalObject obj)throwsIllegalAccessException {try{return introspect(obj, null);

}finally { //clean visited cache before returning in order to make//this object reusable

m_visited.clear();

}

}//we need to keep track of already visited objects in order to support//cycles in the object graphs

private IdentityHashMap m_visited = new IdentityHashMap(100);private ObjectInfo introspect(final Object obj, finalField fld)throwsIllegalAccessException {//use Field type only if the field contains null. In this case we will//at least know what's expected to be//stored in this field. Otherwise, if a field has interface type, we//won't see what's really stored in it.//Besides, we should be careful about primitives, because they are//passed as boxed values in this method//(first arg is object) - for them we should still rely on the field//type.

boolean isPrimitive = fld != null &&fld.getType().isPrimitive();boolean isRecursive = false; //will be set to true if we have already//seen this object

if (!isPrimitive) {if(m_visited.containsKey(obj)) {

isRecursive= true;

}

m_visited.put(obj,true);

}final Class type = (fld == null || (obj != null && !isPrimitive)) ?obj

.getClass() : fld.getType();int arraySize = 0;int baseOffset = 0;int indexScale = 0;if (type.isArray() && obj != null) {

baseOffset=unsafe.arrayBaseOffset(type);

indexScale=unsafe.arrayIndexScale(type);

arraySize= baseOffset + indexScale *Array.getLength(obj);

}finalObjectInfo root;if (fld == null) {

root= new ObjectInfo("", type.getCanonicalName(), getContents(obj,

type),0, getShallowSize(type), arraySize, baseOffset,

indexScale);

}else{final int offset = (int) unsafe.objectFieldOffset(fld);

root= newObjectInfo(fld.getName(), type.getCanonicalName(),

getContents(obj, type), offset, getShallowSize(type),

arraySize, baseOffset, indexScale);

}if (!isRecursive && obj != null) {if(isObjectArray(type)) {//introspect object arrays

final Object[] ar =(Object[]) obj;for (finalObject item : ar)if (item != null) {

root.addChild(introspect(item,null));

}

}else{for (finalField field : getAllFields(type)) {if ((field.getModifiers() & Modifier.STATIC) != 0) {continue;

}

field.setAccessible(true);

root.addChild(introspect(field.get(obj), field));

}

}

}

root.sort();//sort by offset

returnroot;

}//get all fields for this class, including all superclasses fields

private static List getAllFields(finalClass type) {if(type.isPrimitive()) {returnCollections.emptyList();

}

Class cur=type;final List res = new ArrayList(10);while (true) {

Collections.addAll(res, cur.getDeclaredFields());if (cur == Object.class) {break;

}

cur=cur.getSuperclass();

}returnres;

}//check if it is an array of objects. I suspect there must be a more//API-friendly way to make this check.

private static boolean isObjectArray(finalClass type) {if (!type.isArray()) {return false;

}if (type == byte[].class || type == boolean[].class

|| type == char[].class || type == short[].class

|| type == int[].class || type == long[].class

|| type == float[].class || type == double[].class) {return false;

}return true;

}//advanced toString logic

private static String getContents(final Object val, finalClass type) {if (val == null) {return "null";

}if(type.isArray()) {if (type == byte[].class) {return Arrays.toString((byte[]) val);

}else if (type == boolean[].class) {return Arrays.toString((boolean[]) val);

}else if (type == char[].class) {return Arrays.toString((char[]) val);

}else if (type == short[].class) {return Arrays.toString((short[]) val);

}else if (type == int[].class) {return Arrays.toString((int[]) val);

}else if (type == long[].class) {return Arrays.toString((long[]) val);

}else if (type == float[].class) {return Arrays.toString((float[]) val);

}else if (type == double[].class) {return Arrays.toString((double[]) val);

}else{returnArrays.toString((Object[]) val);

}

}returnval.toString();

}//obtain a shallow size of a field of given class (primitive or object//reference size)

private static int getShallowSize(finalClass type) {if(type.isPrimitive()) {final Integer res =primitiveSizes.get(type);return res != null ? res : 0;

}else{returnobjectRefSize;

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值