虚拟机入门一(基本概念梳理)
运行时数据区域
JVM是运行在操作系统之上的,与硬件没有直接的交互
-
类加载器(Class loader):java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java 类,即 java.lang.Class类的一个实例。
- 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库(jre/lib/rt.jar),是用原生C++代码来实现的
- 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库(jre/ext/*.jar)。Java 虚拟机的实现会提供一个扩展库目录。
- 应用类加载器(AppClassLoader ):我们写的大部分java类都是由他加载
- 实例,以上三种是父子类关系加载,从上到下,也叫作双亲委派机制。
-
程序计数器:可以看成当前线程所执行字节码的行号指示器,是一块较小的内存空间。为了保证线程切换后能恢复到正确的位置,所以需要个线程有一个独立的程序计数器,所以我们称这类内存区域为线程私有
-
java虚拟机栈:该区域也是线程私有,他的生命周期和线程相同。虚拟机栈描述的是java方法执行的内存模型:每个方法在执行的同时都会创建一个zhan栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法的调用过程相当于栈帧在虚拟机中入栈到出栈的过程。
局部变量表存放编译期间的可知的各种基本类型、对象引用类型。一个方法需要在栈中分配多大的局部变量空间是完全确定的,运行期间不会改变局部变量表的大小。
-
本地方法栈:与虚拟机栈发挥的作用是非常的相似,只不过本地方法栈是为Native方法服务。
-
java堆:该区域是线程共享也是虚拟机所管理内存中最大的一块。该区域主要的目的在于存放实例,几乎所有的对象实例都是在这里分配的。因为JIT编译器以及栈上分配…所以所有对象在堆上分配也没有那么绝对了。java堆有时候也被称为GC堆(Garbage Collected Heap),因为他是垃圾收集器管理的主要区域。java堆细分为:新生代和老年代;在细分一点:Eden空间、From Survivor空间、To Survivor空间
-
方法区:该区域是线程共享用于存储已被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等数据。很多人更愿意把他叫做永久代, 因为HotSpot设计团队选择把GC分代收集扩展至方法区。这个区域的回收非常的严格,所以回收效果很糟糕
-
运行时常量池:是方法区的一部分。Class文件除了有类的版本、字段、方法、接口等描述信息,还有一项信息是常量池,用于存放编译器生成的各种字面量和符号引用
垃圾收集算法
确定对象是否已死
首先需要明确三点
- 哪些内存需要回收
- 什么时候回收
- 如何回收
如何确定对象是否已死
-
引用计数法
给对象添加一个引用计数器,每当有一个地方引用他,计数器值就加1;当引用失效是值就减一。任何时刻计数器为0的对象就为死。缺点:当两个对象相互引用对方时,就不会出现计数器为0的情况。虚拟机不是采用计数算法来判断对象是否存活
-
可达性分析算法
在主流的商用程序语言(java、c#…)的主流实现中都是通过可达性分析(Reachability Analysis)来判定对象是否存活。基本思想:通过一些列的称为’GC Roots’的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时
java语言可作为GC Roots的对象包括下面几种
1- 虚拟机栈(栈帧中的本地变量表)中引用的对象
2- 方法区中静态属性引用的对象
3- 方法区中常量引用的对象
4- 本地方法中JNI(一般所说Native方法)引用的对象
引用
通过上面的分析可以知道,不管是引用计数算法判断对象的引用数量还是可达性分析判断对象的引用链是否可达。JDK1.2后,java对引用进行扩充,分为以下四种
- 强引用:类似于Object obj = new Object();这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
- 软引用:用来描述一些还有用但并非必须的对象,在系统内存溢出异常之前,将会对这些对象进行二次回收。
- 弱引用:也是描述非必需对象,但他的强度比软应用更弱一些。被弱引用关联的对象只能生存在下一次垃圾收集发生之前。无论内存是否足够,都会回收只被弱引用关联的对象。
- 虚引用:也被称为幽灵引用或者幻影引用,一个对象是否有虚引用的存在完全不会对其生存时间构成影响,也无法通过该引用来取得一个对象的实例。这个唯一的目的就是对象被收集器回收时收到一个系统通知
生存还是死亡
即使可达性性分析算法中不可达的对象,也并非是‘非死不可’的。这是他们暂时处于缓刑阶段,要宣布一个对象的死亡至少要经历两次标记过程