一、Java内存泄漏:
一些Java对象,它们处于可达状态,但程序以后都不会再访问到它们,那么它们所占用的内存空间也不会被回收,它们所占用的内存空间就会产生内存泄漏。
内存泄漏通常会出现在ArrayList中的remove()方法中,而在源码中,remove()中删除一个元素后,就会将这个元素置null,如果我们不做这步操作的话,很容易会产生内存泄漏。
二、Java垃圾回收机制:
java的垃圾回收机制主要做两件事情:
1、跟踪并监控每个Java对象,当某个对象处于不可达状态时,回收改对象所占用的内存。
2、清理内存分配、回收过程中产生的内存碎片
高效的垃圾回收算法是java程序运行效率的重要体现,避免内存的分配和回收称为应用程序的性能瓶颈。
三、垃圾回收的基本算法:
注意:JVM垃圾回收机制判断某个对象是否可以回收的唯一标准是:是否还有其他的引用指向该对象?如果有,垃圾回收机制就不会回收该对象,否则垃圾回收机制就会尝试回收。
对于一个垃圾回收期的设计算法,主要有如下设计:
1、串行回收(Serial)和并行回收(Parallel):串行回收只用一个CPU进行垃圾回收,并行回收用多个CPU分担进行垃圾回收。显然并行回收的效率更加高,但是其复杂度也很高,而且还容易产生内存碎片。
2、并发执行(Concurrent)和应用程序停止(Stop-the-world):应用程序停止(Stop-the-world)在执行垃圾回收的时候会导致应用程序的暂停,并发执行的垃圾回收不会导致应用程序的暂停,但是并发执行的系统开销更大,而且需要的内存也较大。
3、压缩(Compacting)和不压缩(Non-Compacting)和复制(Copying):压缩的垃圾回收会把所有的活对象搬到一起,然后释放内存;不压缩的垃圾回收知识回收内存,这样会导致更多的内存碎片;显然压缩的垃圾回收更快,不压缩的垃圾回收回收快,但是分配内存慢,且容易产生内存碎片。。复制的垃圾回收是回收过程不易产生内存碎片,但是复制过程需要额外的内存。
四、堆内存的分代回收:
先行的垃圾回收器用分代的方式来采用不同的回收设计,分代是根据对象生成时间的长短,将堆内存分为3代:
堆内存分代回收的基本思路:
(1)绝大多数内存对象不会被长时间引用,这些对象在其Young时期就会被回收
(2)很老的对象和很新的对象之间很少存在相互引用的情况
1、Young(年轻代):只需遍历那些处于可达状态的对象,而且这些对象的数量较少,可复制成本不大,采用复制算法较好。
2、Old(老年代):使用串行标记压缩算法,这种算法可以避免复制Old代的大量对象,回收过程中不会产生大量的内存碎片。
3、Permanent(永久代):对于那些需要加载很多类的服务器程序,需要加大Permanent代内存,否则可能因为内存不足而导致程序终止。
五、常见的垃圾回收器:
1、串行回收器(Serial Collector):对Young代采用串行复制算法,对Old代采用串行标记压缩算法
2、并行回收器:只有多CPU并行的机器才能发挥其优势,主要用于对Old代进行垃圾回收
3、并行压缩回收器(Parallel Compacting Collector)
4、并发标志-清理回收器(Mark-Sweep CMS)