Jvm的知识点汇总共6个大方向:内存模型、类加载机制、GC垃圾回收是比较重点的内容。性能调优部分偏重实际应用,重点突出实践能力。编译器优化和执行模式部分偏重理论基础,主要掌握知识点。
各个部分的内容如下:
1>内存模型部分:程序计数器、方法区、堆、栈、本地方法栈的作用,保存哪些数据;
2>类加载部分:双亲委派的加载机制以及常用类加载器分别加载哪种类型的类;
3>GC部分:分代回收的思想和依据,以及不同垃圾回收算法实现的思路、适合的场景;
4>性能调优部分:常用的jvm优化参数的作用,参数调优的依据,要了解常用的jvm分析工具能分析哪类问题,以及使用方法;
5>执行模式部分:解释、编译、混合模式的优缺点,了解java7提供的分层编译技术。需要知道JIT即时编译技术和OSR也就是栈上替换,知道C1、C2编译器针对的场景,其中C2针对server模式,优化更激进。在新技术方面可以了解一下java10提供的由java实现的graal编译器。
6>编译优化部分:前端编译器javac的编译过程、AST抽象语法树、编译期优化和运行期优化。编译优化的常用技术,包括公共子表达式的消除、方法内联、逃逸分析、栈上分配、同步消除等。明白了这些才能写出对编译器友好的代码。
Jvm的内容相对来说比较集中,但是对知识深度的掌握要求较高,建议面试前重点加强。
Jvm内存相关考点
1.详解-jvm内存模型
jvm内存模型主要指运行时的数据区,包括5个部分。
栈也叫方法栈,是线程私有的,线程在执行每个方法时都会同时创建一个栈帧,用来存储局部变量表、操作栈、动态链接、方法出口等信息。调用方法时执行入栈,方法返回时执行出栈。
本地方法栈与栈类似,也是用来保存线程执行方法时的信息,不同的是,执行java方法使用栈,而执行native方法使用本地方法栈。
程序计数器保存着当前线程所执行的字节码位置,每个线程工作时都有一个独立的计数器。程序计数器为执行java方法服务,执行native方法时,程序计数器为空。
栈、本地方法栈、程序计数器这三个部分都是线程独占的。
堆是jvm管理的内存中最大的一块,堆被所有线程共享,目的是为了存放对象实例,几乎所有的对象实例都在这里分配。当堆内存没有可用的空间时,会抛出OOM异常。根据对象存活的周期不同,jvm把堆内存进行分代管理,由垃圾回收器来进行对象的回收管理。
方法区也是各个线程共享的内存区域,又叫非堆区。用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,
jdk1.7中的永久代和1.8中的metaspace都是方法区的一种实现。
面试回答此知识点相关问题时,要答出两个要点:一个是各部分的功能,另一个是哪些线程共享,哪些独占。
2.详解-jmm内存可见性
jmm是java内存模型,与刚才讲到的jvm内存模型是两回事,jmm的主要目标是定义程序中变量的访问规则,如图所示,所有的共享变量都存储在主内存中共享。每个线程有自己的工作内存,工作内存中保存的是主内存中变量的副本,线程对变量的读写等操作必须在自己 的工作内存中进行,而不能直接读写主内存中的变量。
在多线程进行数据交互时,例如线程a给一个共享变量赋值后,由线程b来读取这个值,a修改完变量是修改在自己的工作区内存中,b是不可见的,只有从a的工作区写回到主内存,b再从主内存读取到自己的工作区才能进行进一步的操作。由于指令重排序的存在,这个写-读的顺序有可能被打乱。
因此jmm需要提供原子性、可见性、有序性的保证。
3、详解-jmm保证
主要介绍下jmm如何保证原子性、可见性,有序性。
-
jmm保证对除long和double外的基础数据类型的读写操作是原子性的。另外关键字Synchronized也可以提供原子性保证。Synchronized的原子性是通过java的两个高级的字节码指令monitorenter和monitorexit来保证的。
-
jmm可见性的保证,一个是通过Synchronized,另外一个就是volatile。volatile强制变量的赋值会同步刷新回主内存,强制变量的读取会从主内存重新加载,保证不同的线程总是能够看到该变量的最新值。
-
jmm对有序性的保证,主要通过volatile和一系列happens-before原则。volatile的另一个作用就是阻止指令重排序,这样就可以保证变量读写的有序性。
happens-before原则包括一系列规则,如
程序顺序原则,即一个线程内必须保证语义串行性;
锁规则,即对同一个锁的解锁一定发生在再次加锁之前;
此外还包括happens-before原则的传递性、线程启动、中断、终止规则等。
网友评论