学习目标:
《深入理解java虚拟机》
学习内容:
一图了解java虚拟机
1.JVM运行时数据区
(1)程序计数器
1.程序计数器,是线程私有的。
2.程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
3.它是唯一一个在Java虚拟机规范中没有规定任何OutofMemoryError情况的区域。
(2)java虚拟机栈
1.java虚拟机栈,也是线程私有的。
2.首先栈是运行时的单位,而堆是存储的单位。即:栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。堆解决的是数据存储的问题,即数据怎么放,放哪里。
3.虚拟机栈溢出原因:扩展的栈容量无法申请到足够的内存。
(3)本地方法栈
1.本地方法栈,也是线程私有的。
2.Java虚拟机栈于管理Java方法的调用,而本地方法栈用于管理本地方法的调用。
3.在Hotspot JVM中,直接将本地方法栈和虚拟机栈合二为一。
(4)java堆
1.java堆,非线程私有。
2.“几乎”所有的对象实例都在堆分配内存,但并非全部。因为还有一些对象是在栈上分配的(逃逸分析,标量替换)
3.堆溢出原因:不断的创建对象。
(5)方法区(元空间jdk1.8)
1.方法区,非线程私有。
2.它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。
3.jdk1.8后字符串常量分配在堆上,运行时常量在元空间上(本地内存)。
面试题:说一下JVM内存模型吧,有哪些区?分别干什么的?
2.对象的内存布局
面试题:java对象头里有什么。
3.String的intern()方法
1.intern是一个native方法,调用的是底层C的方法
2.字符串常量池池最初是空的,由String类私有地维护。在调用intern方法时,如果池中已经包含了由equals(object)方法确定的与该字符串内容相等的字符串,则返回池中的字符串地址。否则,该字符串对象将被添加到池中,并返回对该字符串对象的地址。
4.垃圾回收相关算法
标记阶段:
1.引用计数算法
引用计数器有一个严重的问题,即无法处理循环引用的情况。这是一条致命缺陷,导致在Java的垃圾回收器中没有使用这类算法。
2.可达性分析算法
1.可达性分析算法是以根对象集合(GCRoots)为起始点,按照从上至下的方式搜索被根对象集合所连接的目标对象是否可达。
2.GC Roots可以是哪些元素?
(1)虚拟机栈中引用的对象,比如:各个线程被调用的方法中使用到的参数、局部变量等。
(2)本地方法栈内JNI(通常说的本地方法)引用的对象
(3)方法区中类静态属性引用的对象,比如:Java类的引用类型静态变量
(4)方法区中常量引用的对象,比如:字符串常量池(StringTable)里的引用
(5)所有被同步锁synchronized持有的对象
(6)Java虚拟机内部的引用。
(7)基本数据类型对应的Class对象,一些常驻的异常对象(如:NullPointerException、OutofMemoryError),系统类加载器。
(8)反映java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。
清除阶段:
1.标记-清除算法
2.复制算法
3.标记-压缩算法
4.分代收集算法
5.分区算法(G1)
面试题:
1.常见的垃圾回收器算法有哪些,各有什么优劣?
2.GC Roots有哪些?
5.垃圾回收器
1.CMS:低延迟
1.CMS的垃圾收集算法采用标记-清除算法,并且也会”Stop-the-World”。(涉及STW的阶段主要是:初始标记 和 重新标记)。
2.CMS工作流程
初始标记(Initial-Mark)阶段:在这个阶段中,程序中所有的工作线程都将会因为“Stop-the-World”机制而出现短暂的暂停,这个阶段的主要任务仅仅只是标记出GC Roots能直接关联到的对象。一旦标记完成之后就会恢复之前被暂停的所有应用线程。由于直接关联对象比较小,所以这里的速度非常快。
并发标记(Concurrent-Mark)阶段:从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。
重新标记(Remark)阶段:由于在并发标记阶段中,程序的工作线程会和垃圾收集线程同时运行或者交叉运行,因此为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,并且也会导致“Stop-the-World”的发生,但也远比并发标记阶段的时间短。
并发清除(Concurrent-Sweep)阶段:此阶段清理删除掉标记阶段判断的已经死亡的对象,释放内存空间。由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的
2.G1:区域化分代式
1.G1将内存划分为一个个的region。内存的回收是以region作为基本单位的。Region之间是复制算法,但整体上实际可看作是标记-压缩(Mark-Compact)算法,两种算法都可以避免内存碎片。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。尤其是当Java堆非常大的时候,G1的优势更加明显。
2.回收流程
(1)应用程序分配内存,当年轻代的Eden区用尽时开始年轻代回收过程;G1的年轻代收集阶段是一个并行的独占式收集器。在年轻代回收期,G1 GC暂停所有应用程序线程,启动多线程执行年轻代回收。然后从年轻代区间移动存活对象到Survivor区间或者老年区间,也有可能是两个区间都会涉及。
(2)当堆内存使用达到一定值(默认45%)时,开始老年代并发标记过程。
(3)标记完成马上开始混合回收过程。对于一个混合回收期,G1 GC从老年区间移动存活对象到空闲区间,这些空闲区间也就成为了老年代的一部分。和年轻代不同,老年代的G1回收器和其他GC不同,G1的老年代回收器不需要整个老年代被回收,一次只需要扫描/回收一小部分老年代的Region就可以了。同时,这个老年代Region是和年轻代一起被回收的。
(4)举个例子:一个Web服务器,Java进程最大堆内存为4G,每分钟响应1500个请求,每45秒钟会新分配大约2G的内存。G1会每45秒钟进行一次年轻代回收,每31个小时整个堆的使用率会达到45%,会开始老年代并发标记过程,标记完成后开始四到五次的混合回收。
3.令人震惊、革命性的 ZGC
1.ZGC:ZGC收集器是一款基于Region内存布局的,(暂时)不设分代的,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-压缩算法的,以低延迟为首要目标的一款垃圾收集器。
2.ZGC的工作过程可以分为4个阶段:并发标记 - 并发预备重分配 - 并发重分配 - 并发重映射 等。
3.ZGC几乎在所有地方并发执行的,除了初始标记的是STW的。所以停顿时间几乎就耗费在初始标记上,这部分的实际时间是非常少的。
面试题:
1.JVM有哪三种垃圾回收器?
2.回收的过程以及STW次数?
6.类加载子系统
1.类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。
2.ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。
3.加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)
类加载过程
1.加载阶段
加载
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
加载class文件的方式:从本地系统中直接加载;通过网络获取,典型场景:Web Applet;从zip压缩包中读取,成为日后jar、war格式的基础;运行时计算生成,使用最多的是:动态代理技术。
2.链接阶段
链接分为三个子阶段:验证 -> 准备 -> 解析
验证(Verify)
目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全
主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。
准备(Prepare)
为类变量(static变量)分配内存并且设置该类变量的默认初始值,即零值
这里不包含用final修饰的static,因为final在编译的时候就会分配好了默认值,准备阶段会显式初始化
注意:这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中
解析(Resolve)
将常量池内的符号引用转换为直接引用的过程
3.初始化阶段
双亲委派机制
Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。
双亲委派机制优势:避免类的重复加载。
几种破坏双亲委派模型
JDBC、热部署、模块化
7.JIT编译
在部分商用虚拟机中(如HotSpot),Java程序最初是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”。为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler,下文统称JIT编译器)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。