一直以来都想写博客去记录自己学习历程,但却迟迟没有动手,总觉得自己的水平还有待提高,不能写出什么高质量的博文去分享。但发现自己错了,重要的不是一定要做好,而是一定要去做。
今天做开发的时候又碰到java.lang.OutOfMemoryError了,查了一些资料,看了一些博文,做了以下的几点总结:
- 导致OutOfMemory的一些原因:
1.程序中过多使用static类型引用变量(static类型变量的生命周期同于类的生命周期,不能够被及时的释放掉)
2.程序中使用了大量的递归或者出现无限递归
3.程序中出现了大量的嵌套循环(建议嵌套不超过四层)或者死循环
4.一次性向数据库查询的数据量过大(数据量达到10万条以上)
5.程序中有容器存放的是对象的应且使用完未清空
6.大量的使用了非字面量字符串的+操作 - 堆溢出相关的java内存模型
java的内存模型中有一块叫做堆(heap), 它是JVM所管理的内存中最大的一块,被所有的线程共享,是线程不安全的,所有的对象实例和数组都在堆上分配。堆又可以细分为两个部分:新生代(YongGen)、老年代(OldGen),其中新生代还可以分为:Eden区、From Survior区、To Survior区。
堆是GC管理的主要区域,其中GC又分为新生代GC(Minor GC)和老年代GC(Full GC)。对象在Eden区和From Surivior区中出生后,经过一次Minor GC(清理了Eden区和From Surivior区)仍存活的话,则用复制算法copy到To Surivior区中,并使之年龄加1,多次Minor GC后仍存活年龄达到某个值时(比如15次Minor GC后仍存活,年龄达到15),则该对象会被Copy到老年代。 在老年代中,Full GC采用标记-清楚算法清理垃圾,当进行Full GC时,新生代中的对象会被尽量清空,提前进入到老年代。Full GC可能会产生很多的内存碎片。
总结:当对象大于新生代剩余内存时,该对象会被放入老年代,当老年带仍放不下该对象时,会出发Full GC,垃圾收集后仍放不下该对象,则会触发java.lang.OutOfMemoryError异常。