在java虚拟机的内存可以分为三个区域:
- 栈
- 堆
- 方法区
栈
栈的规则:先进后出,后进先出
栈的里面放局部变量,操作数,方法出口等
栈的好处,系统自动发配,速度快
栈是一个连续的空间
堆
存储已创建好的对象,和数组,数组也是对象,堆不是一个连续空间,速度慢
方法区
用来存储程序中永远是不变的或者唯一的内容,代码,字符串变量,静态属性,静态方法
方法区实际也是堆,只是存储类,常量的信息
内存回收
内存管理就是对对象内存的管理,就是对对象的空间分配和释放
对象的内存分配用new关键字创建对象即可
对对象的释放,将对象赋值为null即可,垃圾回收器负责回收所有"不可达"对象的内存地址
内存回收过程
发现无用的对象
回收无用对象占用的空间
判断对象是否为无用对象
引用计数法
逻辑: 在堆中存储内对象时,在对象头用一个计数器counter,如果一个对象增加了一个引用与之相连,则计数器就加1,如果减少一个引用,则计数器减1,如果这个计数器为0时,说明这个对象就是一个无用的对象,它就会被释放占在堆中的对象空间
引用计数法的缺点:
当两个引用互相引用对方,导致他们的引用不为0,其实他们已经无用了,这个时候我们就没办法解决了.
可达性分析算法
以GC Roots的对象为起点,从这些节点开始向下搜素,搜索所走的路径叫做引用链,当一个对象到GC Roots没有任何引用链相连时,则说明这个对象是不可用的.
通用的分代垃圾回收机制
Java中的分代回收机制是:不同的对象的声生命周期是不一样的,因此不同生命周期的对象可以采取不同的回收算法,以便提高效率,
我们将对象分为三种状态:年轻代、年老代、持节代 ,Java虚拟机分Eden、Survivor和Tenured/Old空间
年轻代
所有新生成的对象都是存储在Eden区中,年轻代的目标就是尽可能快速的收集哪些生命周期短的对象,当年轻代(Eden区)满的时候,这个时候就会触发Minor GC机制,将无用的对象清理掉,然后用效率较高的复制算法将剩下的对象复制年老代中。
年老代
在年轻代中经历了N(默认为15)次,仍然存活的对象,就会被放在年老代中,因此可以这样认为年老代都是存储一些生命周期比较长的对象,当年老代满的时候,我们需要用Major GC和Full GC(全量回收),来一次大扫除,全面清理年轻代和年老代
持节代
持节代用于放静态文件,如:java类、方法等。持久代对垃圾回收没有显著影响。
Minor GC机制:
清理Eden区的对象,当Eden区满了,就会触发一次Minor GC机制,清理无用的对象,将有用的对象复制到Survivor1和Survivor2 区中(两个区的大小都相等,但是同一时刻,一个在用,一个是空的)
Major GC机制:
用于处理年老代.
Full GC机制:
用于处理年轻代和年老代区域,但是成本比较高,对系统性能产生影响
垃圾回收过程
-
新创建的对象绝大数都放在Eden区
-
当Eden区满了,就会触发Minor GC机制,将无用的对象清理掉,将剩下的对象复制到Servivor1,同时清空Eden区域
-
当Eden区再次满了,会将Servivor1中的不能被清空的对象复制到Servivor2中,然后清空Servivor1中的对象,然后再用Minor GC机制将无用的对象清理掉,然后把Eden区剩下的对象复制到Servivor1中,
-
重复多次,将Servivor中经过15次都未被清理掉的对象,则复制到年老代
-
当Old区满了,则会触发一个一次完整地垃圾回收(FullGC),之前新生代的垃圾回收称为(minorGC)