Java对象占用内存大小的计算

复制即用,不用搞什么代理包,花里胡哨的烦死人。算长度就用sizeOfObj这个代码算的是实际总内存大小,代码简单易懂,要改自己改

package util;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.Queue;

import sun.misc.Unsafe;

public class ObjSize {
	//对象头 8
    public static final int OBJ_BASIC_LEN = 8;  
    //指针 64为默认开启压缩,也就是4,不压缩就是8
    public static final int OBJ_REF_LEN = 4;  
    //数组长度4
    public static final int ARRAY_BASIC_LEN = 4;  
    //reference指针压缩4 不压缩8
    public static final int REF_LEN = 4;
    
    public static final int ALIGN = 8;  
    
	private static Unsafe u;
	static {
		  try  
	        {  
	            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");  
	            theUnsafe.setAccessible(true);    
	            u = (Unsafe) theUnsafe.get(null);   
	        }  
	        catch (Exception e)  
	        {  
	            e.printStackTrace();  
	        }  
	}
	private enum TypeLength{
		布尔(1),字节(1),字符(2),短整(2),
		整形(4),单精(4),长整(8),双精(8);
		private int bt;
		private TypeLength(int bt){
			this.bt=bt;
		}
		public int getBt() {
			return bt;
		}
	}
	 public static int sizeOfObj(Object o) {
		 int bt=0; 
		 if(o==null) {
			 return bt;
		 }
		 Class initclass=o.getClass();
		 Object initO=o;
		 if(o.getClass().isArray()) {
			 return sizeOfArray(o);
		 }
		 //用非阻塞队列
		 Queue q=new LinkedList();
		 q.offer(o.getClass());
		 //创建子对象并不会创建父对象,私有属性和构造方法不会被继承
		 //但是在计算的时候还是要把他的私有属性带进去
		 while(q.size()!=0) {
		 Class oz=(Class)q.poll();
		 //父类不加头部
		 if(oz==initclass)
		 bt+=OBJ_BASIC_LEN+REF_LEN;//头部12
		 
		 Field[] fs=oz.getDeclaredFields(); 
//		 Class father=clazz.getSuperclass();
//		 Field[] _ffs=father.getDeclaredFields();
//		 List<Field> ffsList=new ArrayList<Field>();
//		 for(int i=0;i<_ffs.length;i++) {
//			 //判断属性是不是私有的,getFields这个方法可以直接过滤掉private,但连protected也会过滤
//			 if(_ffs[i].isAccessible())
//			 ffsList.add(_ffs[i]);
//		 }
//		 Field[] ffs=(Field[]) ffsList.toArray(new Field[ffsList.size()]);
//		 fs=Arrays.copyOf(fs, fs.length+ffs.length);
//		 System.arraycopy(ffs, 0, fs, fs.length-ffs.length, ffs.length);
		 if(fs.length!=0) {
			for(Field f:fs) {
				if(Modifier.isStatic(f.getModifiers()))
					continue;
				Class type=f.getType();
				
				if(type==boolean.class)
					bt+=TypeLength.布尔.getBt();
				else if(type==byte.class)
					bt+=TypeLength.字节.getBt();
				else if(type==char.class)
					bt+=TypeLength.字符.getBt();
				else if(type==short.class)
					bt+=TypeLength.短整.getBt();
				else if(type==int.class)
					bt+=TypeLength.整形.getBt();
				else if(type==float.class)
					bt+=TypeLength.单精.getBt();
				else if(type==double.class)
					bt+=TypeLength.双精.getBt();
				else if(type==long.class)
					bt+=TypeLength.长整.getBt();
				else if(type==void.class) {}
				else if(type.isArray()) {
					bt+=REF_LEN;//4
					Object oo = u.getObject(initO, u.objectFieldOffset(f));
					if(oo!=null)
					bt+=sizeOfArray(oo);
				}
				else {
					bt+=REF_LEN;//4
					Object oo = u.getObject(initO, u.objectFieldOffset(f));
					if(oo!=null)
					bt+=sizeOfObj(oo);
				}
			}
		 }
		 
		 Class father=oz.getSuperclass();
		 if(father!=null) {
			 q.offer(father);
		 }
		 }
		 if(bt%ALIGN>0) {
			 bt+=ALIGN-(bt%ALIGN);
		 }
		 return bt;
	 }
	 //数组
	 private static int sizeOfArray(Object os) {
		 if(os==null) {
			 return 0;
		 }
		 int length=Array.getLength(os);
		 int bt=OBJ_BASIC_LEN+OBJ_REF_LEN+ARRAY_BASIC_LEN;//16
		 Class type=os.getClass();
		 if(type == boolean[].class)
				bt+=TypeLength.布尔.getBt()*length;
		 else if(type==byte[].class)
				bt+=TypeLength.字节.getBt()*length;
		 else if(type==char[].class)
				bt+=TypeLength.字符.getBt()*length;
		 else if(type==short[].class)
				bt+=TypeLength.短整.getBt()*length;
		 else if(type==int[].class)
				bt+=TypeLength.整形.getBt()*length;
		 else if(type==float[].class)
				bt+=TypeLength.单精.getBt()*length;
		 else if(type==double[].class)
				bt+=TypeLength.双精.getBt()*length;
		 else if(type==long[].class)
				bt+=TypeLength.长整.getBt()*length;
			else {
				Object[] uh=new Object[length];
				 for(int i=0;i<length;i++) {
					 uh[i]=Array.get(os, i);
				 }
				for(Object o:uh) {
					bt+=REF_LEN+sizeOfObj(o);
				}
			}
			if(bt%ALIGN>0) {
				bt+=ALIGN-(bt%ALIGN);
			}
			return bt;
	 }
	
	 
}

注意这个方法不能计算链表式数据结果对象 如集合linkedList的大小,因为链表的pre和next互相调用。需要自作改进哦

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值