好程序员java教程分享之jvm篇,在前面的文章中,介绍了JVM内存模型分为:堆区、虚拟机栈、方法区、本地方法区和程序计数器,其中堆区是JVM中最大的一块内存区域,在Java中的全部对象实例都保存在此区域,它能被全部线程共享。java
在Java中还有一个重要的机制:GC(垃圾收集器),堆是GC管理的主要区域,本文会带你们了解GC机制。程序员
GC的简介算法
GC(Garbage Collection)垃圾收集机制是Java一个重要特性。不一样于C/C++语言须要程序员本身管理内存的回收,并且这样作每每容易出错,致使内存泄漏等严重问题。jvm
Java程序员不用编写回收内存的代码,由于Java有GC机制,它是一个特殊的后台线程,该线程对JVM中的内存进行标记,并肯定哪些须要回收,再经过必定的回收策略自动回收内存,它在后台一直运行,保证JVM不会出现内存溢出的问题。学习
对象回收的算法线程
那么GC是如何判断某个对象的内存须要回收呢?GC须要判断该对象已死,也就是再也不被调用,如何判断对象再也不被调用呢?对象
这里有两种算法:blog
一、引用计数算法教程
二、可达性分析算法内存
引用计数算法
该算法给每一个对象分配一个计数器,当有引用指向这个对象时,计数器加1,当指向该对象的引用失效时,计数器减一。最后若是该对象的计数器为0时,java垃圾回收器会认为该对象是可回收的。
优势:
一、实时性高,只要对象计数器为0就进行回收,不用等到内存不足的时候。
二、在垃圾回收过程当中,应用无需挂起。
三、更新对象的计数器时,只是影响到该对象,不会扫描所有对象。
缺点:
一、每次引用对象时,都会更新计数器,有时间消耗
二、不能解决循环引用问题
那什么是循环引用问题呢?咱们看下面这段代码:
1. class ClassA{
2. ClassB b;
3. }
4. class ClassB{
5. ClassA a;
6. }
7. public static void main(String[] args){
8. ClassA a = new ClassA();
9. ClassB b = new ClassB();
10. a.b = b;
11. b.a = a;
12. a = null;
13. b = null;
14. }
上面的a、b两个对象虽然都赋值为null,可是都不能回收,由于存在循环引用,它们的计数器不为0.
可达性分析算法
该算法经过一种被称做“GC Root”的对象做为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证实此对象时不可用的。
以下图:
在Java语言中,可做为GC Roots对象包括下面几种:
1)虚拟机栈中引用的对象
2)方法区中类静态属性引用的对象
3)方法区常量池中引用的对象
3)本地方法栈中JNI引用的对象
再回头看前面这段代码,虽然a和b对象的引用计数都不为0,可是它们做为GC Root对象,最后都赋值为null,致使引用不可达,这样两个对象都是能够被回收的。
总结
本文咱们学习了JVM中的垃圾收集(GC)机制,GC是一个在后台持续运行的线程,帮助咱们回收JVM堆中的对象内存,保证JVM不会内存溢出。
如何判断对象内存须要回收,有两个算法:引用计数算法和可达性分析算法。
引用计数算法经过判断对象的引用计数为0,就标记该对象内存能够回收,可是不能很好的解决循环引用问题;可达性分析算法经过GC Root向下搜索,若是引用链相连则对象可达,不然标记对象不可达,能够进行回收,这种算法能很好解决对象循环引用问题。