哪些内存需要回收?什么时候回收?如何回收?
0. 哪些内存需要回收
内存分布
- 程序计数器:就是PC指针,程序执行到哪里他指到哪里,唯一一点是每个线程有一个PC指针,是线程私有的,因为Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。
- java栈
也是线程私有的,用于存储局部变量、动态链接、方法入参、方法返回值等,一个方法执行结束就是一个java栈出栈入栈过程。 - 本地方法栈
和java栈唯一区别是执行的是native方法,java栈执行的是java方法,native方法一般指c、c++方法 - java堆
是java虚拟机管理的最大块内存,是所有线程共享的一块内存,也是垃圾回收器管理的主要部分,gc回收说的主要是这块内存 - 方法区
是各个线程共享的内存,用于存储加载的类信息、常亮、静态常亮、编译后的代码等数据
上面的java堆和方法区就是gc要回收的区域
1. 什么时候回收
java堆
- 引用计数算法
给对象添加引用计数器,有地方引用它加1,引用失效减1,gc扫描到这个对象的时候如果计数器为0就回收,最大的缺点是两个对象互相引用,别的地方没有引用这两个对象的时候就没办法回收这两个对象 -
可达性分析算法
从gc Root开始向下搜索,能到达的对象不能回收,不能到达的对象就可以回收了.
方法区
- 常量
比如字符串常量"abc",没有任何String对象引用它,也没有其他地方引用它,那就可以回收他 - 类
- 该类的所有实例都被回收了
- 加载该类的ClassLoader已经被回收了
- 该类对应的java.lang.Class对象没有在任何地方被引用
满足以上条件就可以回收这个无用类
如何回收?
- 标记-清除算法
需要回收的对象标记出来,gc回收时清除一遍 - 复制算法
把内存空间平分两份,一份使用,需要回收时把使用的一份中未标记的内存复制到另一份,然后使用过的全部清除 - 标记-整理算法
需要回收的对象标记出来,gc回收时移动到一端,把另一端的全部清零 - 分代收集算法
把内存分为新生代和老生代,新生代用复制算法,老生代用标记-清除或者标记-整理算法
网友评论