Java自动内存管理
在讲解内存管理之前,首先需要了解对象和对象引用的区别
对象是类的一个实例,以人这个类为例,Person是我们定义的一个类
public class Person{}
public Person person;
person = new Person();
而new Person()是新建了一个对象,person是对这个对象的引用,它可以指向任意一个对象。
1.1 java运行时区域(什么地方存什么)
程序计数器:可以理解为线程当前执行位置的标记,用途:线程切换。
栈
>虚拟机栈:每一个方法执行时创建一个栈帧,方法的执行代表着栈帧在在内存区换入换出。这里面存储着方法参数和局部变量,类型为基本数据类型、数组/对 象的引用。
>本地方法栈:作用和VM stacks类似,只不过服务于native方法。图片引自参考2.
堆:存放对象实例。垃圾回收主要指针对堆的回收策略。
方法区:类信息,常量,静态变量(static 、class),包含常量池
1.2 垃圾回收机制
垃圾回收(Garbage Collection,GC)自动清空堆中不再使用的对象。
如果一个对象没有引用,我们称这个对象不可达,垃圾回收用于释放不可达的对象所占据的内存,这是垃圾回收的基本原则。
垃圾回收分为两个步骤:判断这个对象是否已死(不可达)和清除这个对象。
1.2.1 对象已死吗
> 引用计数。给对象添加一个计数引用器,当为0时,判断对象不可达。缺点:无法解决相互引用的情况。ObjA.instance = ObjB;ObjB.instance = ObjA; ObjA和ObjB已经不能访问,但引用计数法无法通知垃圾回收机制。
改进:以栈和static数据为根(root),从根出发,跟随所有的引用,就可以找到所有的可到达对象。也就是说,一个可到达对象,一定被根引用,或者被其他可 到达对象引用。如下图:引自参考2
1.2.2. 垃圾回收策略
-
- 标记-清除(mark-sweep)算法:标记谁不可达,然后删除.
缺点:a.效率,两个步骤效率都不高;b,导致产生大量的空间碎片
-
- 复制-清除:将内存划等分为两块区域A和B,扫描A,将可达的对象复制到B中,然后将A清空。缺点:代价太大
改进:由于对象绝大部分生命周期较短,将内存按照一定比例(通常8:1:1)划分为A,B,C,将A和B可达的对象存储到C中,将A和B 清空,A和C作为上一步骤 的A和B。
-
- 标记-整理,标记过程类似,存活的对象向一端移动。
参考:1,
2, 重点推荐
3,《深入理解Java虚拟机:JVM高级特性与最佳实践》.pdf