您的位置:首页 > 其它

JVM内存管理和垃圾回收

2016-05-22 10:44 232 查看

JAVA内存管理

最近复习了JAVA中的内存分配和垃圾回收,在此做个总结。

JAVA中的内存主要分为以下三种:永久存储区(方法区)、堆区和栈区。永久存储区存放的class类,主要包括类的静态变量和方法;堆区存放的是类对象,主要存放对象的成员变量,也是垃圾回收的对象;栈区存放的是基本类型变量和对象的引用。这三种内存不足时都会产生OutOfMemoryError。

补充:JAVA的常量池里面存放的对象有两种:final类型变量和直接声明的字符串常量。

String str1="abcde";
存放在常量池里面。

String str2=new String("abcde")则存放在堆里面。

JAVA垃圾标记

JAVA能够对堆区内存进行自动垃圾回收。垃圾回收包括垃圾标记和垃圾回收。
垃圾标记有引用计数法和跟搜索算法。引用计数法是对每个对象设置一个引用计数器,当对象被引用时计数器加1,否则减1,当计数器为0时,就当做垃圾进行回收。它具有简单高效的特点。但是它不能解决对象互相引用的问题,也就是两个死亡的对象互相引用。
跟搜索算法是将一个跟对象集合作为跟,然后沿着引用路径对对象进行搜索,如果有对象不可达,则将这些对象作为垃圾进行回收,他能有效解决对象互相引用的问题,而且同样具有简单高效的特点。跟对象集合包含以下5个元素有:
1)JAVA栈中的对象引用
2)本地方法栈中的对象引用;
3)运行时常量池中的对象引用
4)方法区中类静态属性的对象引用
5)与一个类对应的唯一数据类型的class对象

JAVA垃圾回收

垃圾回收算法有标记-清除算法、复制算法、标记-压缩算法。
标记清除算法将垃圾回收分为两个阶段:垃圾标记和内存释放。特点:效率低下,会产生内存碎片。
复制算法的具体过程如下:
JAVA的堆区又分为新生代和老年代。新生代又可以分为eden区和to survivor、from survivor区,前者与后面两者之和的比例是8:1,当然这个比例是可以更改的。JAVA中不同的对象具有不同的生命周期,大部分对象的生命周期都非常短,但是有的对象的生命周期非常长,所以将生命周期短的对象存放在新生代中,生命周期长的存放在老年代中。而复制算法主要适用对象就是新生代内存。
当执行一次minor GC后,eden中存活并且还年轻的对象会被复制到to空间,已经经历过一次GC的存放在from空间中的对象如果还年轻的话也会被复制到to空间中。(以下两种情况不会被复制到to空间:1存活对象的年龄超过设定的阈值,会直接晋升到老年代;2to空间内存使用以满,也会直接晋升到老年代)当所有存活对象都复制到to空间后,剩余的对象就被当做垃圾对象进行回收,这就完成了一次minor GC。
执行完minor GC后,eden和from被清空,to空间内容就会和from空间进行互换。
对老年代的full GC垃圾回收主要采用标记压缩算法

JAVA垃圾收集器

概念:1)串行回收和并行回收
串行回收是同一时刻只允许一件事情发生,即使有多个CPU,也只有一个用于垃圾回收,client模式下常用此模式;并行回收同一时刻可以有多个CPU进行垃圾回收,主要用于多CPU工作情况。不过他们都是用复制算法和stop-the-world机制。
2)并发机制和stop-the-world机制
stop-the-world机制是执行回收时程序中所有的线程都被暂停。在新生代因为每次回收时间较短,所以暂停时间不会太长;但在老年代,每次full GC的时间比较长,如果采用此机制延迟时间非常长,就会早场灾难。并行回收是工作线程和垃圾收集线程同时运行或者交叉运行。
serial垃圾收集器:串行收集器,工作于新生代,采用复制算法、stop-the-world机制。适用于单CPU模式。serial old收集器作用于老年代,与前者唯一不同是回收算法是标记压缩算法。
PaiNew收集器是并行收集器,其他的与serial完全相同,可以理解为serial收集器的多线程版本。在单CPU模式中,此收集器因任务切换的原因,效率并不如serial收集器。
Parallel收集器与前者唯一不同是他可以控制程序的吞吐量大小。
CMS是作用于老年代的垃圾收集器,采用并行回收,最大优点是低延迟,采用的是标记压缩算法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: