这个问题不记得是谁提起过,那时没想通是什么原因,这段时间在摸索java对内存对象的管理实现才知道.
1,在阐述这个问题之前首先要了解JVM的垃圾回收实现原理,这个功能是java内存对象管理者的其中一个线程,用于释放内存中不在被使用的对像,其实现过程是依次遍历对象的索引将没有被其他对象应用的对象释放掉.也就是java的垃圾回收只能释放那些没有被引用的对象空间,有很多程序在编写的时候运行很正常,但部署到服务器不久后就有内存溢出.
2,那么集合在程序中造成内存溢出有两种原因:
(1),集合装载的数据量过大,超出了JVM执行的内存范围,这个时候就有内存溢出.通常解决办法是分段读取数据量,减少内存在短时间内的开销,或者加大设 置JVM内存(默认是64M).
(2),集合在程序中被大循环调用,不断在内存中创建无法被垃圾回收机制回收的集合对象,当程序运行到一定时期时集合对象就会沾满内存,造成内存溢出.
比如以下代码:
- <P><FONT style="BACKGROUND-COLOR: #ffffff">public class Demo {
- //定义一个静态变量
- static Integer i=0;
- public static void main(String[] ages){
- //无线循环调用test()方法
- while(true){
- new Demo().test();
- }
- }
- //定义一个被循环调用的方法
- public void test(){
- i++;//i值一直在变
- //定义一个HashMap集合
- HashMap hashMap=new HashMap();
- /*
- *在此hashMap集合并没有跟随该方法的运行结束而被释放.因为集合装载有一个静态常量
- *也就是集合中的元素被其他对象引用,所以垃圾回收机制不能回收hashMap对象
- *而在方法每次执行时都创建一个新的集合去装载一个新的静态元素"i".
- *所以集合会被无限的循环创建对象存在内存中知道内存溢出
- *
- */
- hashMap.put(null, i);
- }
- }</FONT></P>
复制代码 针对第二个问题,目前也有很多解决方案,我个人总结了下,大致有三种:
(1),不要往集合中存入静态元素或者其他生命周期比集合生命周期还要长的元素.以至于使得GC能够回收释放.
(2),如果在大型的程序中,不能确确保集合要存入其他静态变量或者使集合不能在方法运行结束后跟着释放的元素,那么在集合被使用完成后调用clear()方法移除集合中所有元素,以便之后垃圾回收机制能回收释放.
(3),如果在程序中集合要被不断循环创建使用,那么就将该集合写成成员静态身份.防止在循环中不断创建出新的集合实例,同时也减少了程序在循环中不再去创建新集合实例时而消耗的资源.
这是本人一点皮毛的见解,希望路过的大虾别吐槽...
|
|