95%的技术面试必考的JVM知识点都在这,另附加分思路!

概述:知识点汇总

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原则的传递性、线程启动、中断、终止规则等。

二、类加载机制相关考点

1.详解类加载机制? ? ?

类的加载指的是将编译好的class类文件中的字节码读入到内存中,将其放在方法区内并创建对应的Class对象。

类的加载分为加载、链接、初始化,其中链接又包括验证、准备、解析三步。看到图中上半部分深绿色,我们逐个分析:

  • 加载是文件到内存的过程。通过类的完全限定名查找此类字节码文件,并利用字节码文件创建一个Class对象
  • 验证是对类文件内容验证。目的在于确保Class文件符合当前虚拟机要求,不会危害虚拟机自身安全。主要包括四种:文件格式验证,元数据验证,字节码验证,符号引用验证。
  • 准备阶段是进行内存分配。为类变量也就是类中由static修饰的变量分配内存,并且设置初始值,这里要注意,初始值是0或者null,而不是代码中设置的具体值,代码中设置的值是在初始化阶段完成的。另外这里也不包含用final修饰的静态变量,因为final在编译的时候就会分配了。
  • 解析主要是解析字段、接口、方法。主要是将常量池中的符号引用替换为直接引用的过程。直接引用就是直接指向目标的指针、相对偏移量等。
  • 最后是初始化:主要完成静态块执行与静态变量的赋值。这是类加载最后阶段,若被加载类的父类没有初始化,则先对父类进行初始化。

只有对类主动使用时,才会进行初始化,初始化的触发条件包括创建类的实例的时候、访问类的静态方法或者静态变量的时候、Class.forName()反射类的时候、或者某个子类被初始化的时候。

类的生命周期,就是从类的加载到类实例的创建与使用,再到类对象不再被使用时可以被GC卸载回收。这里要注意一点,由java虚拟机自带的三种类加载器加载的类在虚拟机的整个生命周期中是不会被卸载的,只有用户自定义的类加载器所加载的类才可以被卸载。

2.详解类加载器? ??

java自带的三种类加载器分别是:bootstrap启动类加载器、扩展类加载器和应用加载器也叫系统加载器。图右边的桔×××文字表示各类加载器对应的加载目录。启动类加载器加载java home中lib目录下的类,扩展加载器负责加载ext目录下的类,应用加载器加载classpath指定目录下的类。

除此之外,可以自定义类加载器。

java的类加载使用双亲委派模式,即一个类加载器在加载类时,先把这个请求委托给自己的父类加载器去执行,如果父类加载器还存在父类加载器,就继续向上委托,直到顶层的启动类加载器,如图中蓝色向上的箭头。如果父类加载器能够完成类加载,就成功返回,如果父类加载器无法完成加载,那么子加载器才会尝试自己去加载。

这种双亲委派模式的好处,一个可以避免类的重复加载,另外也避免了java的核心API被篡改。

三、其他知识梳理

1.详解分代回收? ???

前面提到过,java的堆内存被分代管理,分代管理主要是为了方便垃圾回收,这样做基于2个事实,第一、大部分对象很快就不再使用,第二,还有一部分不会立即无用,但也不会持续很长时间。

虚拟机中划分为年轻代、老年代、和永久代。

1>年轻代:主要用来存放新创建的对象,年轻代分为eden区和两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象会在两个Survivor区交替保存,达到一定次数的对象会晋升到老年代。

2>老年代:用来存放从年轻代晋升而来的,存活时间较长的对象。

3>永久代:主要保存类信息等内容,这里的永久代是指对象划分方式,不是专指1.7的permGen,或者1.8之后的metaspace。

根据年轻代与老年代的特点,jvm提供了不同的垃圾回收算法。垃圾回收算法按类型可以分为引用计数法、复制法和标记清除法。

其中引用计数法是通过对象被引用的次数来确定对象是否被使用,缺点是无法解决循环引用的问题。

复制算法需要from和to两块相同大小的内存空间,对象分配时只在from块中进行,回收时把存活对象复制到to块中,并清空from块,然后交换两块的分工,即把from块作为to块,把to块作为from块。缺点是内存使用率较低。

标记清除算法分为标记对象和清除不在使用的对象两个阶段,标记清除算法的缺点是会产生内存碎片。

jvm中提供的年轻代回收算法Serial、ParNew、Parallel Scavenge都是复制算法,而CMS、G1、zgc都属于标记清除算法。

本篇文章,对这几个算法就不展开了

?

总结:面试考察点及加分项

1.jvm相关的面试考察点

首先,需要jvm的内存模型和java的内存模型;

其次,要了解的类的加载过程,了解双亲委派机制;

第三,要理解内存的可见性与java内存模型对原子性、可见性、有序性的保证机制;

第四,要了解常用的gc算法的特点、执行过程,和适用场景,例如g1适合对最大延迟有要求的场合,zgc适用于64为系统的大内存服务中;

第五,要了解常用的jvm参数,明白对不同参数的调整会有怎样的影响,适用什么样的场景。例如垃圾回收的并发数、偏向锁设置等

2.相关加分项

如果想要面试官对你留下更好的印象的话,注意这些加分项:?

  • 首先,如果在编译器优化方面有深入的了解的话,会让面试官觉得你对技术的深度比较有追求。例如知道在编程时如何合理利用栈上分配降低gc压力、如何编写适合内联优化等代码等。
  • 其次,如果你能有线上实际问题的排查经验或思路那就更好了,面试官都喜欢动手能力强的同学。例如解决过线上经常full gc问题,排查过内存泄露问题等。
  • 第三,如果能有针对特定场景的jvm优化实践或者优化思路,也会有意想不到的效果。例如针对高并发低延迟的场景,如何调整gc参数尽量降低gc停顿时间,针对队列处理机如何尽可能提高吞吐率等;
  • 第四,如果对最新的jvm技术趋势有所了解,也会给面试官留下比较深刻的印象。例如了解zgc高效的实现原理,了解Graalvm的特点等。

总之,掌握以上具体的JVM考点,才能在面试时应答自如。希望读完此篇文章的你,能做好准备,拿到心仪的Offer。



95%的技术面试必考的JVM知识点都在这,另附加分思路!

原文地址:https://blog.51cto.com/14230003/2385764

时间: 2024-10-06 00:16:02

95%的技术面试必考的JVM知识点都在这,另附加分思路!的相关文章

还没搞懂JVM吗?95%的技术面试必问知识点都在这,还怕面不过?

概述:知识点汇总 jvm的知识点汇总共6个大方向:内存模型.类加载机制.GC垃圾回收是比较重点的内容.性能调优部分偏重实际应用,重点突出实践能力.编译器优化和执行模式部分偏重理论基础,主要掌握知识点. 各个部分的内容如下: 1>内存模型部分:程序计数器.方法区.堆.栈.本地方法栈的作用,保存哪些数据: 2>类加载部分:双亲委派的加载机制以及常用类加载器分别加载哪种类型的类: 3>GC部分:分代回收的思想和依据,以及不同垃圾回收算法实现的思路.适合的场景: 4>性能调优部分:常用的j

Java BAT大型公司面试必考技能视频-1.HashMap源码分析与实现

视频通过以下四个方面介绍了HASHMAP的内容 一. 什么是HashMap Hash散列将一个任意的长度通过某种算法(Hash函数算法)转换成一个固定的值. MAP:地图 x,y 存储 总结:通过HASH出来的值,然后通过值定位到这个MAP,然后value存储到这个MAP中的HASHMAP基本原理 1. KEY 是否可以为空?可以,Null当成一个Key来存储 2. 如果Hash KEY重复了会覆盖吗?会覆盖,但返回旧的值 3. HASHMAP什么时候做扩容?put 的时候,阀值高于或等于0.7

直通大厂:Java必考系列——JVM经典面试题目(含答案)

Q1:类的加载机制是什么?答:类加载到内存中主要有5个阶段,分别为①加载:将Class文件读取到运行时数据区的方法区内,在堆中创建Class对象,并封装类在方法区的数据结构的过程.②验证:主要用于确保Class文件符合当前虚拟机的要求,保障虚拟机自身的安全,只有通过验证的Class文件才能被JVM加载.③准备:主要工作是在方法区中为类变量分配内存空间并设置类中变量的初始值.④解析:将常量池中的符号引用替换为直接引用.⑤初始化:主要通过执行类构造器的<client>方法为类进行初始化,该方法是在

面试必问:JVM类加载机制详细解析

前言 在Java面试中,简历上有写JVM(Java虚拟机)相关的东西,JVM的类加载机制基本是面试必问的知识点. 类的加载和卸载 JVM是虚拟机的一种,它的指令集语言是字节码,字节码构成的文件是class文件.平常我们写的Java文件,需要编译为class文件才能交给JVM运行.可以这么说:C语言代码——>二进制文件——>计算机硬件,就相当于Java代码——>字节码文件——>JVM.JVM将指定的class文件读取到内存里,并运行该class文件里的Java程序的过程,就称之为类的

MySQL面试必考知识点:揭秘亿级高并发数据库调优与最佳实践法则

做业务,要懂基本的SQL语句: 做性能优化,要懂索引,懂引擎: 做分库分表,要懂主从,懂读写分离... 数据库的使用,是开发人员的基本功,对它掌握越清晰越深入,你能做的事情就越多. 今天我们用10分钟,重点梳理一遍以下几方面: 数据库知识点汇总: 数据库事务特性和隔离级别: 详解关系型数据库.索引与锁机制: 数据库调优与最佳实践: 面试考察点及加分项. 知识点汇总 一.数据库的不同类型 1.常用的关系型数据库 Oracle:功能强大,主要缺点就是贵 MySQL:互联网行业中最流行的数据库,这不仅

Android面试必考基础题

(1)<必考题>请写出Android系统架构有几层,分别是哪几层? 考点:Android系统架构 答案:有四层.分别是Linux内核.本地库和Java运行时环境.应用程序框架.应用程序. (2)<必考题>请简要介绍Android的四大组件? 考点:Android四大组件 答案:Android系统有四种组件,这四种组件构成了Android应用的框架,然后由Intent联系这四种组件.Activity用来显示Android的程序界面,一个应用往往有多个界面,所以一个应用中会有多个Act

关于链表所有操作,面试必考C++

1 #include <iostream> 2 #include <stack> 3 using namespace std; 4 //链表的结构体 5 struct ListNode 6 { 7 int m_nValue; 8 ListNode* m_pNext; 9 ListNode() 10 { 11 m_pNext = NULL; 12 } 13 }; 14 //判断链表是否为空 15 bool isEmpty(ListNode* list) 16 { 17 return

【iOS开发-34】自己主动释放池@autoreleasepool的使用注意事项以及ARC机制——面试必考内容

自己主动释放池@autorelease面试频率可能会吧release还要高. (1)在自己主动释放池@autoreleasepool{}中alloc一个对象后(如p1).仍然须要用[p1 autorelease];不过这个语句和[p1 release];不同.后者表示把p1的retainCount-1,而前者只表示把p1放到自己主动释放池中返回一个self,自己主动释放池结束销毁时,统一对里面的对象引用计数retainCount-1. (2)@autoreleasepool{}能够任意创建.也能

【iOS开发-34】自动释放池@autoreleasepool的使用注意事项以及ARC机制——面试必考内容

自动释放池@autorelease面试频率可能会吧release还要高. (1)在自动释放池@autoreleasepool{}中alloc一个对象后(如p1),仍然需要用[p1 autorelease];只是这个语句和[p1 release];不同,后者表示把p1的retainCount-1,而前者仅仅表示把p1放到自动释放池中返回一个self,自动释放池结束销毁时,统一对里面的对象引用计数retainCount-1. (2)@autoreleasepool{}可以随意创建,也可以嵌套使用.