ehcache 默认大小_Ehcache计算Java对象内存大小

在EHCache中,可以设置maxBytesLocalHeap、maxBytesLocalOffHeap、maxBytesLocalDisk值,以控制Cache占用的内存、磁盘的大小(注:这里Off Heap是指Element中的值已被序列化,但是还没写入磁盘的状态,貌似只有企业版的EHCache支持这种配置;而这里maxBytesLocalDisk是指在最大在磁盘中的数据大小,而不是磁盘文件大小,因为磁盘文中有一些数据是空闲区),因而EHCache需要有一种机制计算一个类在内存、磁盘中占用的字节数,其中在磁盘中占用的字节大小计算比较容易,只需要知道序列化后字节数组的大小,并且加上一些统计信息,如过期时间、磁盘位置、命中次数等信息即可,而要计算一个对象实例在内存中占用的大小则要复杂一些。

计算一个实例内存占用大小思路

在Java中,除了基本类型,其他所有通过字段包含其他实例的关系都是引用关系,因而我们不能直接计算该实例占用的内存大小,而是要递归的计算其所有字段占用的内存大小的和。在Java中,我们可以将所有这些通过字段引用简单的看成一种树状结构,这样就可以遍历这棵树,计算每个节点占用的内存大小,所有这些节点占用的内存大小的总和就当前实例占用的内存大小,遍历的算法有:先序遍历、中序遍历、后序遍历、层级遍历等。但是在实际情况中很容易出现环状引用(最简单的是两个实例之间的直接引用,还有是多个实例构成的一个引用圈),而破坏这种树状结构,而让引用变成图状结构。然而图的遍历相对比较复杂(至少对我来说),因而我更愿意把它继续看成一颗树状图,采用层级遍历,通过一个IdentitySet纪录已经计算过的节点(实例),并且使用一个Queue来纪录剩余需要计算的节点。算法步骤如下:

1. 先将当前实例加入Queue尾中。

2. 循环取出Queue中的头节点,计算它占用的内存大小,加到总内存大小中,并将该节点添加到IdentitySet中。

3. 找到该节点所有非基本类型的子节点,对每个子节点,如果在IdentityMap中没有这个子节点的实例,则将该实例加入的Queue尾。

4. 回到2继续计算直到Queue为空。

剩下的问题就是如何计算一个实例本身占用的内存大小了。这个以我目前的经验,我只能想到遍历一个实例的所有实例字段,根据每个字段的类型来判断每个字段占用的内存大小,然后它们的和就是该实例占用的总内存的大小。对于字段的类型,首先是基本类型字段,byte、boolean占一个字节,short、char占2个字节,int、float占4个字节,double占8个字节等;然后是引用类型,对类型,印象中虚拟机规范中没有定义其大小,但是一般来说对32位系统占4个字节,对64位系统占8个字节;再就是对数组,基本类型的数组,byte每个元素占1个字节,short、char每个元素占2个字节,int每个元素占4个字节,double每个元素占8个字节,引用类型的数组,先计算每个引用元素占用的字节数,然后是引用本省占用的字节数。

以上是我对EHCache中计算一个实例逻辑不了解的时候的个人看法,那么接下来我们看看EHCache怎么来计算。

Java对象内存结构(以Sun JVM为例)

参考:http://www.importnew.com/1305.html,之所以把参考链接放在开头是因为下面基本上是对链接所在文章的整理,之所以要整理一遍,一是怕原链接文章消失,二则是为了加深自己的理解。

在Sun JVM中,除数组以外的对象都有8个字节的头部(数组还有额外的4个字节头部用于存放长度信息),前面4个字节包含这个对象的标识哈希码以及其他一些flag,如锁状态、年龄等标识信息,后4个字节包含一个指向对象的类实例(Class实例)的引用。在这头部8个字节之后的内存结构遵循一下5个规则:

规则1: 任何对象都是以8个字节为粒度进行对齐的。

比如对一个Object类,因为它没有任何实例,因而它只有8个头部直接,则它占8个字节大小。而对一个只包含一个byte字段的实例,它需要填上(padding)7个字节的大小,因而它占16个字节,典型的如一个Boolean实例要占用16个字节的内存!

class MyClass {

byte a;

}

[HEADER:    8 bytes] 8

[a:             1 byte ] 9

[padding:    7 bytes] 16

规则2: 类属性按照如下优先级进行排列:长整型和双精度类型;整型和浮点型;字符和短整型;字节类型和布尔类型;最后是引用类型。这些属性都按照各自的单位对齐。

在Java对象内存结构中,对象以上述的8个字节的头部开始,然后对象属性紧随其后。为了节省内存,Sun VM并没有按照属性声明时顺序来进行内存布局,而是使用如下顺序排列:

1. 双精度型(double)和长整型(long),8字节。

2. 整型(int)和浮点型(float),4字节。

3. 短整型(short)和字符型(char),2字节。

4. 布尔型(boolean)和字节型(byte)&

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值