JVM相关

JVM相关_第1张图片

JVM相关_第2张图片

 GC算法:JVM相关_第3张图片

基本部分

1、堆和栈有什么区别?

1、堆和栈是JVM内存中的两个不同区域,作用也不同。对象的分配是在堆上进行的。

栈中包含一系列的栈帧,是来存储局部变量、操作数栈、动态链接、方法出口等信息。

2、堆是线程共享的区域,栈是线程私有的区域。

类加载部分

1、Java中为什么要采用PDM方式来实现类加载呢?有几个目的

防止内存中出现多份同样的字节码。如果没有 PDM 而是由各个类加载器自行加载的话,用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都能加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证,同时,也会给虚拟机的安全带来隐患。
双亲委派机制能够保证多加载器加载某个类时,最终都是由一个加载器加载,确保最终加载结果相同。
这样可以保证系统库优先加载,即便是自己重写,也总是使用Java系统提供的System,自己写的System类根本没有机会得到加载,从而保证安全性。

2、jvm中对象的结构是什么?

对象由对象头、实例数据、对其填充三部分组成。

对象头包括1、对象运行时数据(GC分代年龄、符号引用等) 2、指针类型: 指向 对象的类的元数据类型  3、如果是一个对象数组,则还包括   数组的长度信息

实例数据就是  对象的真正有效的信息,包括从父类继承来的以及自定义的

对齐填充是指  对象的起始地址必须是8字节的整倍数。

GC部分

1、什么是需要被回收的垃圾?

运行程序中没有任何指针指向的对象,就是需要被回收的垃圾。

2、为什么要进行垃圾回收?

计算机内存有限,如果不回收,就会一直占用内存空间,最终导致OOM。

3、早期的垃圾回收机制是什么样的?有什么缺点?

早期垃圾回收:使用者自己手动申请空间,手动释放空间。

缺点一旦忘了释放,会造成内存泄露。

4、java的垃圾回收机制形式?优缺点是什么?

自动内存管理:  优点: 降低内存溢出与内存泄露风险,让程序员更专注于业务逻辑。

                           缺点: 一点出现问题,难以定位与改错。

5、垃圾回收发生的区域是哪里?

垃圾回收发生在堆和方法区。 重点是堆。

频繁发生在年轻代(堆)、较少发生在老年代(堆)、基本不动 元空间(方法区)。

6、垃圾回收过程主要有哪几个阶段?

标记阶段、清除阶段

7、标记阶段,如何判断对象已死?

主要有两种方法

①、引用计数法

        定义:对每个对象保存一个计数器属性,如果有其他对象引用了,则+1,引用失效后-1,若   为0,则表示可以回收。

        优点:实现简单、便于识别、判定效率高,回收没有延迟。

        缺点

                1、计数器也占用空间,增加空间消耗。

                2、每次引用变化,都要计算。增加时间消耗。

                3、无法解决循环引用问题。(根本缺点)

   java没有采用引用计数法,python使用了,python采用手动解除和使用弱引用weakref的方式来应对以上缺点。

②、可达性分析法:

定义:以根节点集合GCRoots为起始点,按照从上至下的方式搜索被根节点集合直接或间接连接的对象,视为可达对象。非可达对象则视为可回收对象。

优点:可以解决循环引用问题

8、GCRoots包括哪几种对象?

①、虚拟机栈中引用的对象

②、本地方法栈Jni中引用的对象

③、方法区类静态属性所引用的对象

④、方法区中常量所引用的对象

⑤、所有被同步锁synchronized持有的对象

⑥、java虚拟机内部的引用

除此之外,根据垃圾回收器及垃圾回收区域的不同,也有一些可能被临时作为GCRoot的对象。

9、GC时 STW (stop the world)的原因?

可达性分析法必须在一个能够保证一致性的快照中进行

10、在GC中对象的三种状态?

可触及、可复活、可回收

11、如何判断对象可回收?(是问题7的进一步细化说法)

一个对象是否可回收要经过两个标记阶段。

1、经过可达性分析法 判断 对象是否可达,若可达,则不可收回。若不可达,标记为 不可达。

2、对不可达对象进行判断,是否重写了finalize()方法,若没有重写,则 标记为可回收。

若重写了 ,则执行,执行后对象可能被复活,则不可回收。若没有被复活,则可回收。

3、finalize()只能被执行一次。若已执行过,则第二次运行到此时直接将对象标记为可回收。

12、垃圾回收的清除阶段有哪些算法?

1、标记-清除算法

2、复制算法

3、标记-压缩算法

13、标记-清除算法

1、算法描述:   ①、标记可达对象   ②、对堆内存进行遍历,清除非可达对象

2、缺点:①、效率不算高   ②、GC时,停止整个应用程序  ③、清理出的内存空间是不连续的,容易产生内存碎片。

详细说下第三个缺点原因:

标记-清除算法的清除并不是真正的清除,而是将可以被清除的对象地址保存在空闲的地址列表中,下次有新对象需要加载时,逐个判断空闲列表中每个垃圾的空间是否够存放,如果够,则存放。

14、分代收集算法                

并不是一种新的算法,而是一种算法思想,不同代采用不同的垃圾收集算法,组合使用。如年轻代使用 复制算法,老年代使用标记-压缩算法。

15、增量收集算法

在以上提到的算法,GC中都会STW,如果时间过长,会影响用户体验。因此让垃圾回收线程每次只回收一小片区域,与应用线程交替运行,直到垃圾回收完成。

优点是降低了延迟,单次STW时间很短。缺点是频繁的线程和上下文切换消耗,使得垃圾回收的成本上升,系统吞吐量下降。

16、垃圾回收的相关概念

System.gc()、  Runtime.getRuntime().gc()

显式的调用垃圾回收,但不能保证程序立刻进行GC,原因 “”安全点、安全区域的概念“”

内存溢出(OOM)

原因:没有空闲内存,垃圾回收器也无法提供更多的内存。

没有空闲内存的原因,jvm的堆内存设置的不够,可以通过-Xms、 -Xmx调整

代码中创建了大量的大对象,并且长时间不能被垃圾回收。

内存泄露(Memory Leak)

描述: 一个对象不会被程序用到了,但垃圾回收器却不能回收他。

举例:1、一个需回收的对象   在单例模式中的单例对象中被引用。因为单例模式的声明周期跟应用程序一样长,所有这个对象就无法被回收。2、一些提供了close方法的资源未关闭导致内存泄露。如数据库连接、网络连接(socket)和io连接

STW   (stop the world)

gc发生过程中,整个应用程序线程都会被暂停等待,没有响应。

垃圾回收的并行与并发

并行: 同一时间点可同时执行

并发: 同一时间段同时执行,同一时间点只有一个执行。

安全点、安全区域

应用线程执行过程中并非在所有地方都能够停顿下来开始GC,只有在特定的位置才能进行GC,这些位置就被称为安全点或安全区域。通常会选择应用程序一些执行时间较长的指令作为安全点。如方法的调用、循环跳转、异常跳转

如何保证GC发生时,可以使应用程序线程在最近的安全点停顿下来呢?

1、抢先式中断。

首先中断所有线程,如果还有线程不在安全点上,就恢复线程,让线程跑到安全点

2、主动式中断

设置一个中断标志,让线程运行到安全点时主动轮询这个标志,为真,则自己中断挂起。

引用的四种类型

强引用:  引用存在就不会被回收。

软引用:  引用存在,但内存不足时,被回收

弱引用:  引用存在,但只要垃圾回收器发现了它,就会被回收

虚引用:  对对象的生命周期起不到任何影响,只是为了让对象被收回时,能够接受系统通知。

17、如何去分析、了解一个JDK的版本变化?

1、从语法层面看变化

2、从API层面看变化

3、底层优化:主要指JVM的优化

垃圾收集器

18、垃圾回收器的分类

1、按线程数分 :串行垃圾回收器、并行垃圾回收器

2、按工作性质分: 并发式垃圾回收器、独占式垃圾回收器

3、按内存碎片处理方式分:  压缩式、非压缩式

4、按工作的内存空间分: 年轻代的垃圾回收器、老年代的垃圾回收器

 19、评判垃圾回收器的性能指标有哪些?

1、吞吐量

2、延迟

3、内存占用情况

20、Java常见的垃圾回收器有哪些?

年轻代垃圾回收器:

serial GC   : 第一款垃圾回收器,用于年轻代,单线程工作,他是所有收集器中额外内存消耗最小的;对于单核处理器或者处理器核心数较少的环境来说,可以获得最高的单线程手机效率,适用于运行在客户端模型下的虚拟机。

Parnew : serial 的多线程版本

Parallel Scavenge: 

目标是达到一个可控制的吞吐量。

主要参数:

-XX:MaxGCPauseMills    最大单次垃圾回收消耗时间: >0的毫秒数

-XX:GCTimeRatio   :控制运行用户线程时间与垃圾回收时间的比值

-XX:+UserAdaptiveSizePolicy   自适应调节策略,虚拟机自动调整新生代大小及伊甸园去与幸存区比例。

老年代垃圾回收器:

serial old : serial的老年代版本,单线程,使用标记-整理算法

Parallel old : 在JDK1.4中发布,在jdk1.6后, Parallel成为默认的垃圾回收器.多线程收集。使用标记-整理算法

CMS: 以获取最短回收停顿时间为目标的收集器。使用标记-清除算法。

优点:并发收集、低停顿。

缺点:1、对处理器资源十分敏感。处理器资源很少时,慢

           2、无法处理浮动垃圾

           3、基于标记-清除算法,因此会有内存碎片化问题

工作过程可以分为

1、初始标记:  标记GCRoots节点直接关联的对象。此过程会STW

2、并发标记:  从GCRoots根节点遍历整个对象图。此过程不会STW 

3、重新标记:     由于并发标记阶段不会STW,所以引用可能会变动,所以需要修改部分标记。此过程会STW

4、并发清除:  清除标记阶段标记的可回收对象

G1 :  里程碑式的垃圾收集器,开创了收集器面向局部收集的设计思路和基于Region的内存布局形式和具有优先级的区域回收方式,基于标记-复制算法,jdk9以后成为 默认的服务端垃圾回收器。

目标是  在延迟可控的情况下获取尽可能高的吞吐量

优点:停顿更小

缺点:

1、需要耗费更多内存:需要java堆的10%-20%的内存来维持收集器工作

工作过程可以分为

1、初始标记:  标记GCRoots节点直接关联的对象。此过程会STW

2、并发标记:  从GCRoots根节点遍历整个对象图。此过程不会STW 

3、最终标记      此过程会STW

4、筛选回收      此过程会STW

CMS和G1的比较和选择?

G1基于标记-复制算法,CMS基于标记-清除算法。

因此CMS会有内存空间碎片化问题,G1不会有。

但G1的内存占用和运行额外执行负载比CMS高。

内存占用来说,二者都使用卡表来处理跨代指针,但G1是基于Region的,所以卡表更为复杂,开销更大。

因此各有优缺点,需根据实际情况判断,据作者经验,在小内存应用上,CMS的表现大概率好于G1,在大内存应用上,G1更容易发挥优势。这个java堆容量的平衡点通常在6g-8g之间。

Epsilon、

Shenandoah: 第一款非Oracle开发的垃圾回收器

ZGC :  基于Region内存布局,不设分代,使用了读屏障、染色指针,和内存多重映射等技术来实现可并发的标记-整理算法的,以低延迟为首要目标的一款垃圾收集器,JDK11中引入

核心重点就是 可并发的标记整理算法的实现。

多重映射:将多个不同的虚拟内存地址映射到同一物理内存地址上;是使用染色指针技术的伴生产物

优点: 支持“NUMA-Aware”的内存分配。

“NUMA-aware” ,非统一内存访问架构,是一种为多处理器或者多核处理器的计算机所设计的内存架构。

支持NUMA的内存分配的仅有 parallel scavenge 、zgc

ZGC是未来发展的趋势,目前让处于实验阶段。

如何选择合适的垃圾收集器?

主要应该从以下三个方面考虑:

1、应用程序的主要关注点是什么?

如果是服务端的数据分析、科学计算等,则更为管住吞吐量

如果是SLA应用,更关注延迟

如果是客户端或嵌入式,更为关注 内存占用

2、运行应用的基础设施如何?

3、使用jdk的发行商是什么?

垃圾收集器参数?

见另一篇博客

调优相关:

1、JVM调优相关的指令有哪些?

jps         作用:jvm process status tools,用于检测系统中所有的hotspot虚拟机进程

jstat       作用 : 监测jvm运行时的状态信息

jmap      作用:  生成 堆 dump文件

jhat        作用:  分析堆dump文件

jstack     作用: 生成虚拟机当前时刻的线程快照

jinfo       作用: 实时查看和调整jvm运行参数

2、JVM调优工具有哪些?

jdk自带的: 1、jconsole    2、 jvisualvm   

第三方的:  1、 MAT         2、GChisto

3、JVM性能调优方法有哪些?

1、调整堆大小

-Xmx            设置堆的大小

2、设置新生代大小,新生代不能太小,否则会有大对象涌入老年代

-XX:NewSize     新生代大小

-XX:NewRatio    新生代和老年代占比

-XX:SurvivorRatio     伊甸园区与  survivor区占比

3、根据实际情况自主设定垃圾回收器

-XX:+UseParNewGC         新生代用

-XX:+UseConcMarkSweepGC    老年代用

你可能感兴趣的:(java面试题,java,后端,jvm)