背景说明:
最近工作中有一个业务,暂时考虑将每条记录对象放入内存,目标峰值定为50W条数据(50W个对象)。
在使用jvisualvm监控中发现,在内存中Bean实例数为50W,大小为4000W字节整(不是大约,是详细数据),但是在堆中显示的是实例数50W,大小为6000W字节(同上)。
在查阅《深入理解java虚拟机》中发现下图,我怀疑是否是因为jvisualvm监控中显示的大小为实例对象的大小,不包含对象中包含的属性和对象。但为何无论空对象,还是有赋值的对象实例堆大小和内存大小不一致。我想问下各位,内存和堆中大小为何不一致。
最近工作中有一个业务,暂时考虑将每条记录对象放入内存,目标峰值定为50W条数据(50W个对象)。
在使用jvisualvm监控中发现,在内存中Bean实例数为50W,大小为4000W字节整(不是大约,是详细数据),但是在堆中显示的是实例数50W,大小为6000W字节(同上)。
在查阅《深入理解java虚拟机》中发现下图,我怀疑是否是因为jvisualvm监控中显示的大小为实例对象的大小,不包含对象中包含的属性和对象。但为何无论空对象,还是有赋值的对象实例堆大小和内存大小不一致。我想问下各位,内存和堆中大小为何不一致。
这里说JVM 本身也要占用内存,就像 OS 内核和 C 运行时一样,而 JVM 占用的内存是本机堆的子集。
这个也挺好验证的,楼主内存中Bean实例数为10W的时候看堆大小就可以了
http://www.ibm.com/developerworks/cn/java/j-codetoheap/
还有用jvisualvm的visual GC插件看过具体的新生代老年代么
你给的信息太少,猜都不好猜
int forNumber = 500000;
for(int i = 0; i < forNumber ; i++){
AbnorAccountBean bean = new AbnorAccountBean();
hm.add(bean);
}Bean对象的属性数量增加,减少都会影响大小。无论有没有值。
我差不多理解的就是显示的对象大小只记录的是引用大小
比如一个int = 4B
如果Bean里面有10个int 对象的大小就是40B + 他自身的引用大小
如果Bean里面还有别的引用,也只计算引用的大小
字符串由专门的一个String和char[]统计,类里面加载的String只记录的是String引用的大小。
所以最后只能大概估算了一下,50W全部属性赋值的对象,基本变量大小≈57M 字符常量≈6M time≈16 在加上其他一些对象 50W全部属性赋值的对象大概100M。
简单点说,对象的大小就是对象内所以属性的引用大小的和。
方法区,类加载区的大小没计算。
比如说我这个功能如果放入内存要占100M内存,如果放数据库,每天50W数据,保存30天就是1500W数据,
你每次查数据你觉得是在内存中使用好,还是每次从数据库查好,哪种对系统的压力要小?
各种优缺点都知道,才能正确的根据项目需求确定业务的解决方案啊。
简单就是效率,速度,服务器硬件压力之间的平衡点。
我居然为了你3个字回复这么多。是不是很荣幸
如果非要将50w的对象放入内存,还是推荐将这些数据放入方法区吧(设为静态static),这样不会影响minor GC也不会影响Full GC,也就是说对你的堆内存没什么影响了,缺点就是需要较大的方法区
还是放到数据库吧,对mysql还有oracle这种数据库来说,加好索引200w的数据是毫无压力的
文件的实际大小和占用空间是两个不同概念 文件的大小是以字节byte计量的 而占用空间是以簇计量的
为了更好地管理磁盘空间和更高效地从硬盘读取数据,操作系统规定一个簇中只能放置一个文件的内容,因此文件所占用的空间,只能是簇的整数倍;而如果文件实际大小小于一簇,它也要占一簇的空间。所以,一般情况下文件所占空间要略大于文件的实际大小,只有在少数情况下,即文件的实际大小恰好是簇的整数倍时,文件的实际大小才会与所占空间完全一致。
加上这两个参数-XX:+PrintHeapAtGC -XX:+PrintGCDetails,然后看看GC的耗时,内存的拷贝情况吧