深入理解Java虚拟机读书笔记---垃圾回收与内存分配
垃圾收集(Garbage Collection,GC),垃圾回收主要考虑三个方面的事情:
- 哪些内存需要回收?
- 什么时候回收?
- 如何回收?
Java内存
运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随
线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每一个
栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此几个区域的内存分配和回收都
具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时
,内存自然就跟随着回收了。而Java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,
一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,
这部分内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存。
可达性分析算法
垃圾回收首先得判断对象是否存活,如果对象已死,那么自然该回收内存,java中判断对象是否存活的算法是
可达性分析算法,这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,
搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连
(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的,也就是对象已死。
如下图:对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达
的,所以它们将会被判定为是可回收的对象
java中可以作为为GC Roots的对象包括下面几种:
- 虚拟机栈(机栈中的本地标量表)中引用的对象
- 方法区中类静态属性引用端详
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
如何判定对象死亡
可达性分析算法即使能找出所有不可达的对象,但是也不能直接回收他们,因为此时并没有宣告一个对象真正的死亡
要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达
性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,
筛选的条件是此对象是否有必要执行finalize()方法。finalize()方法是对象逃脱回收的最后机会。
回收方法区
永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类。其中回收常量的方式与java堆中的
回收方式基本一致。
无用类的判别:
- java堆中不存在任何实例
- 加载该类的ClassLoader已经被回收
-
该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该
类的方法
垃圾收集算法
- 标记-清除算法 缺点:效率,标记清除后产生大量碎片
- 复制算法
- 标记-整理算法
- 分代收集算法
HotSpot的算法实现
oopMap在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译过程中,也
会在特定的位置记录下栈和寄存器中哪些位置是引用,这样GC在扫描的时候就直接知道这些信息。
更多相关文章
- 使用js模仿java的实体类对类/对象进行get操作
- Java常见对象之String
- 基于内容估计文本宽度的算法
- 来谈谈JAVA面向对象 - 鲁班即将五杀,大乔送他回家??
- 对一个JavaScript对象数组进行排序。
- 算法竞赛入门经典(分数化小数)
- 关于几个位运算的算法分析
- java使用compareTo实现一个类的对象之间比较大小
- 跪求一个java抽奖中奖算法的实现,在线等,急。。。。。。。。。。。