首页 >> 大全

春招面试题总结--jvm

2023-12-22 大全 31 作者:考证青年

1、jvm内存区域 写在前面 1、基本问题 2、拓展问题 1.1运行时内存区域

**程序计数器:**记录下一条指令地址,从而实现如顺序执行、循环跳转等等;在多线程中,存在线程切换,程序计数器可以记录当前线程地址,方便线程切换回来以后继续执行。

**虚拟机栈:**存放编译期可知的各种基本数据类型和对象引用。

**本地方法栈:**为虚拟机使用到的方法服务。

**堆:**存放对象实例。另外堆中还有字符串常量池。

关于堆中内存区域的分配:堆中分eden区、s区、old区,新生对象被放在eden区,eden区满出发垃圾收集,并采用可达性分析标记,被标记的存活对象被放到s1区,其余对象杀死;再次向eden区放入新生对象,满后,用可达性分析分析eden区和s1区对象存活情况,存活的对象被放到s2区,此时s1区清空,如此往复循环。当对象年龄达到阈值15以后会被放入老年代,另外如果某个年龄超过了s区内存的一半,取这个年龄和年龄阈值之间更小的值作为新阈值。

**方法区:**存放类名、字段、静态成员、方法。方法区在深入理解java虚拟机这本书中是一个逻辑概念,并不是一个真正意义上的物理分区,真正的物理分区叫做永久代(1.7)/元空间(1.8)。

​ 在使用永久代时,使用两个参数限制它的初始大小和最大大小,分别是和,这样可能会抛出,而元空间使用的是直接内存,受本机可用内存的限制,虽然也可能会产生溢出,但是几率会小很多,且可以加载的类也更多。

1.2、 虚拟机对象探秘 1.2.1、对象的创建

**类加载检查:**当遇到new指令时,去常量池检查有没有这个对象的引用,并且检查这个引用代表的类有没有被加载过,如果没有,则进行相应的类加载。

**分配内存:**为新生对象分配内存——指针碰撞(内存规整);空闲列表(内存不规整)。

——>内存分配的并发问题(创建对象操作在实际开发中很频繁,需要确保线程安全):

1、CAS+失败重试,保证更新操作原子性

2、TLAB, 为每一个线程预先在 Eden 区分配一块儿内存,JVM 在给线程中的对象分配内存时,首先在 TLAB 分配,当对象大于 TLAB 中的剩余内存或 TLAB 的内存已用尽时,再采用上述的 CAS 进行内存分配

**初始化零值:**为分配到的内存空间初始化零值,保证java代码可以不赋初值使用。

**设置对象头:**对对象进行必要的设置。

**执行init方法:**此时从虚拟机角度,对象已经产生了,但从程序视角来看对象创建才刚开始,在new指令后紧接一个init方法,把对象按照程序猿的意愿进行初始化。

1.2.2、对象的内存布局

在 虚拟机中,对象在内存中的布局可以分为 3 块区域:对象头、实例数据和对齐填充。

**对象头:**第一部分用于存储对象自身的运行时数据mark word(哈希码、GC 分代年龄、锁状态标志等等),另一部分是类型指针class point,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。

**实例数据:**程序中定义的各种类型的字段内容。

**对齐填充部分:**仅起占位作用,对象地址大小必须是8字节的整数倍。

2、JVM垃圾回收 写在前面 2.1 堆内存常见分配策略 2.2 对象死亡 2.2.1 如何判断一个对象已经无效 2.2.2 对象死亡一定会被回收吗

没有被可达性分析标记的对象并不是非死不可,它们处于一个缓刑阶段,要真正宣告死亡还要经历两次标记。首先是进行可达性分析,没有与GC Roots相连的对象将会被第一次标记并进行一次筛选,筛选条件时这个对象有没有必要执行方法,如果覆盖了会把它放到F-Queue队列里,进行第二次标记。

2.2.3 关于方法

​ 如果一个对象覆盖了 () 方法,那么在真正被宣告死亡的时候,至少需要经过两次标记。第一次被标记的时候会被放在 一个 F-Queue 队列中,() 方法是对象逃脱死亡命运的最后一次机会。在第二次标记的时候,如果该对象成功与引用链(GC-Roots)上的任何一个对象关联,那么它仍然可以存活下来,否则将会被垃圾收集器回收。

春招面试技巧__春面试教案设计

2.2.4 Full gc

首先明确三个概念:

Minor GC : 从年轻代空间(包括 Eden 和 区域)回收内存 ;

Major GC : 对老年代GC ;

**Full GC :**对整个堆GC, 经常伴随至少一次的Minor GC,但非绝对 。FGC管理的内存比较大,效率比较慢,STW时间较长,所以尽量不要出发FGC。

触发条件:

.gc()

调用.gc()方法会出发full gc.

老年代空间不足

老年代当中存放的对象有以下几种情况:新生代当中存活时间较长(超过一定年龄阈值)的对象、大对象、大数组,如果老年代当中空间不足了,就会出发full gc。

永久代空间不足

永久代就是我们熟知的方法区,其中存放有类的基本信息、常量、静态变量等数据,当系统当中要加载的类、反射的类、调用的方法太多时,永久代可能会占满,出发full gc.

CMS GC时出现 和 mode

对于采用CMS进行老年代垃圾收集的程序而言,要注意日志中是否有 和 mode 两种情况,他们可能会触发full gc.

2.2.5 再谈引用 2.2.6 如何判断一个类是无用类 2.3 JVM调优

目标:减少GC时用户线程的暂停时间

方法:JVM参数设置和垃圾收集器选择

2.3.1 关于STW

**为什么:**如果没有STW,假设在程序运行过程中突然发生了gc,通过可达性分析从gc roots找非垃圾对象,假设我们找完了,因为没有STW,线程会继续往下执行,且执行结束,而这个时候垃圾收集还没有做完,此时线程所占的内存区域会全部被释放掉,意味着gc roots存储的内存空间也被释放掉了,这个时候之前找出的非垃圾对象就会变成新的垃圾。堆当中有几十、上百万的对象,我们通过分析找出非垃圾对象,gc还没有结束对象的状态又变了,变成垃圾对象,难道又返回去把这几十万的对象再遍历一次吗,显然不现实。所以Java开发人员在设计之初,索性用了stw,让用户线程暂停住,把所有的非垃圾对象找出来,把垃圾对象干掉,这样一次gc的时间可能会更快,效率会更高。

2.3.2 JVM参数调优

背景介绍:

调优前:每个对象60M,一旦有对象进入S区,由于超过S区大小的一半,会被存入old区,无法被minor gc回收,根据old区大小,五六分钟old区就会满发生full gc。

调优后:把年轻代变大。

2.3.3 垃圾回收器

1.8默认的垃圾回收:PS+

2.3 垃圾收集算法* 3、执行引擎 4、类加载子系统 4.1 加载

将.class文件加载进内存,存放在方法区,然后创建一个class对象,用来封装类的数据结构。

春招面试技巧__春面试教案设计

–>类加载器:非数组类由java虚拟机直接创建,数组类由类加载器创建,创建完成后均由类加载器加载。

1、 (启动类加载器) :最顶层的加载类, 负责加载 %%/lib目录下的jar包和类 。

2、 (扩展类加载器) :主要负责加载目录 %%/lib/ext 目录下的jar包和类

3、 (应用程序类加载器) : 面向我们用户的加载器,负责加载当前应用下的所有jar包和类。

–>双亲委派模型

java应用程序由若干个.class文件组成,文件之间经常发生调用关系。而在程序启动时,class文件并不会一次性加载进内存,而是根据程序需要,使用类加载机制()来动态的加载某个class文件到内存当中,只有class文件被加载进内存以后才能被其他class文件调用。

**加载类的原理:**使用双亲委派模型来搜索类。 每个实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器( )本身没有父类加载器,但可以用作其它实例的的父类加载器。当一个实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器 试图加载,如果没加载到,则把任务转交给 试图加载,如果也没加载到,则转交给App 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出on异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

**jvm如何判定两个class文件相同:**不仅要判定两个类名是否相同,而且要判定是否由同一个加载。

**优点:**避免重复加载,如果父类已经加载了该类的时候,子类就没有必要再加载一次。也保证了 Java 的核心 API 不被篡改。

**不想用双亲委派模型怎么办:**使用自定义类加载器的话需要继承类。如果不想打破双亲委派模型就重写类中的方法,当父类加载器无法加载时,就会通过这个方法加载。如果想打破就需要重写方法。

4.2 验证

确保class文件的合法性,不会危害虚拟机自身安全。

4.3 准备

为类变量分配内存并且设置初始值。

4.4 解析

将常量池内的符号引用转换为直接引用的过程。

4.5 初始化

4.6 常见面试题 4.6.1 什么是类加载机制?

虚拟机把描述类的数据从class文件中加载到内存中,并对数据进行检验、转换解析和初始化,最终形成能够被虚拟机直接使用的java类型。

4.6.2 Java类加载过程

加载–>验证–>准备–>解析–>初始化–>使用–>卸载

4.6.3 什么时候会发生类加载 使用new关键字实例化对象、调用类的静态方法、读取类的静态字段;触发反射机制时;初始化一个类的时候,如果发现其父类还没有进行初始化;虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先初始化这个主类。 4.6.4 jvm加载class文件的原理机制 4.6.5 类加载器的双亲委派模型是什么?可以被打破吗?为什么?

初始化,最终形成能够被虚拟机直接使用的java类型。

4.6.2 Java类加载过程

加载–>验证–>准备–>解析–>初始化–>使用–>卸载

4.6.3 什么时候会发生类加载 使用new关键字实例化对象、调用类的静态方法、读取类的静态字段;触发反射机制时;初始化一个类的时候,如果发现其父类还没有进行初始化;虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先初始化这个主类。 4.6.4 jvm加载class文件的原理机制 4.6.5 类加载器的双亲委派模型是什么?可以被打破吗?为什么?

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了