10.面试题——JVM

1.JVM是什么?

JVM,也就是 Java 虚拟机,它是 Java 实现跨平台的基石。
Java 程序运行的时候,编译器会将 Java 源代码(.java)编译成平台无关的 Java 字节码文件(.class),接下来对应平台的 JVM 会对字节码文件进行解释,翻译成对应平台的机器指令并运行。
同时,任何可以通过 Java 编译的语言,比如说 Groovy、Kotlin、Scala 等,都可以在 JVM 上运行。

2.组织架构

JVM 大致可以划分为三个部门:类加载器、运行时数据区和执行引擎。
类加载器:负责从文件系统、网络或其他来源加载 Class 文件,将 Class 文件中的二进制数据读入到内存当中。

运行时数据区: JVM 在执行 Java 程序时,需要在内存中分配空间来处理各种数据,这些内存区域主要包括方法区、堆、栈、程序计数器和本地方法栈。

执行引擎: 执行引擎是 JVM 的心脏,负责执行字节码。它包括一个虚拟处理器,还包括即时编译器(JIT Compiler)和垃圾回收器(Garbage Collector)。

3.JVM的内存区域是什么?

JVM 的内存区域可以粗暴地划分为堆和栈
当然了,按照 Java 的虚拟机规范,可以再细分为堆、方法区、程序计数器、虚拟机栈、本地方法栈、等。
其中方法区和堆是线程共享区,虚拟机栈、本地方法栈和程序计数器是线程私有的。

Java 堆(Java Heap)是虚拟机所管理的内存中最大的一块,被所有线程共享,在虚拟机启动时创建。
Java 堆中经常会出现新生代、老年代、Eden空间、From Survivor空间、To Survivor空间等名词

方法区

方法区是一块比较特别的区域,和堆类似,也是各个线程共享的内存区域,用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。
Java 虚拟机规范对它的约束非常宽松,所以方法区的具体实现历经了许多变迁,例如 JDK 1.7 时,方法区被永久代(Permanent Generation)所代替,而在 JDK 1.8 时,永久代被彻底移除,取而代之的是元空间(Metaspace)。

程序计数器

程序计数器(Program Counter Register)也被称为 PC 寄存器,是一块较小的内存空间。它可以看作是当前线程所执行的字节码行号指示器。

Java虚拟机栈

Java 虚拟机栈(Java Virtual Machine Stack),通常指的就是“栈”,它的生命周期与线程相同。
Java 虚拟机栈(JVM 栈)中是一个个栈帧,每个栈帧对应一个被调用的方法。当线程执行一个方法时,会创建一个对应的栈帧,并将栈帧压入栈中。当方法执行完毕后,将栈帧从栈中移除。

本地方法栈

本地方法栈(Native Method Stacks)与虚拟机栈相似
区别在于虚拟机栈是为虚拟机执行 Java 方法服务的,而本地方法栈是为虚拟机使用到的本地(Native)方法服务的。

4.堆和栈的区别是什么?

堆属于线程共享的内存区域,几乎所有的对象都在对上分配,生命周期不由单个方法调用所决定,可以在方法调用结束后继续存在,直到不在被任何变量引用,然后被垃圾收集器回收。
栈就是前面提到的 JVM 栈(主要存储局部变量、方法参数、对象引用等),属于线程私有,通常随着方法调用的结束而消失,也就无需进行垃圾收集。

5.垃圾收集算法了解吗?

标记-清除算法
标记-复制算法
标记-清除-整理算法

6.Minor GC/Young GC、Major GC/Old GC、Mix

部分收集(Partial GC):指目标不是完整收集整个 Java 堆的垃圾收集,其中又分为:

  • 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
  • 老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS 收集器会有单独收集老年代的行为。
  • 混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有 G1 收集器会有这种行为。

整堆收集(Full GC):收集整个 Java 堆和方法区的垃圾收集。

7.Minor GC/Young GC什么时候触发?

新创建的对象优先在新生代 Eden 区进行分配,如果 Eden 区没有足够的空间时,就会触发 Young GC 来清理新生代。

8.什么时候触发Full GC?

条件:

System.gc()等命令触发:System.gc()、jmap -dump 等命令会触发 full gc
Young GC 之前检查老年代:在要进行 Young GC 的时候,发现老年代可用的连续内存空间 < 新生代历次Young GC后升入老年代的对象总和的平均大小,说明本次 Young GC 后可能升入老年代的对象大小,可能超过了老年代当前可用内存空间,那就会触发 Full GC。
Young GC 之后老年代空间不足:执行 Young GC 之后有一批对象需要放入老年代,此时老年代就是没有足够的内存空间存放这些对象了,此时必须立即触发一次 Full GC
老年代空间不足,老年代内存使用率过高,达到一定比例,也会触发 Full GC。
空间分配担保失败( Promotion Failure),新生代的 To 区放不下从 Eden 和 From 拷贝过来对象,或者新生代对象 GC 年龄到达阈值需要晋升这两种情况,老年代如果放不下的话都会触发 Full GC。
方法区内存空间不足:如果方法区由永久代实现,永久代空间不足 Full GC。

9.类加载器有哪些?

启动类加载器(Bootstrap ClassLoader)用来加载 java 核心类库,无法被 java 程序直接引用。
扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。
用户自定义类加载器 (user class loader),用户通过继承 java.lang.ClassLoader 类的方式自行实现的类加载器

10.JVM 调优参数

-Xmx3550m:设置 JVM 最大可用内存为 3550M。
-Xms3550m:设置 JVM 初始内存为 3550m。注意:此值一般设置成和-Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存。
-Xmn2g:设置年轻代大小为 2G。整个 JVM 内存大小=年轻代大小+ 年老代大小+持久代大小。此值对系统性能影响较大,Sun 官方推荐配置为整个堆的3/8。-Xss256k:设置每个线程的栈大小。JDK5.0 以后每个线程栈大小为1M,以前每个线程栈大小为 256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。
-XX:NewRatio=4:设置年轻代(包括 Eden 和两个 Survivor 区)与年老代的比值(除去持久代)。设置为 4,则年轻代与年老代所占比值为 1:4。(该值默认为2)-XX:SurvivorRatio=4:设置年轻代中 Eden 区与 Survivor 区的大小比值。设置为4,则两个 Survivor 区与一个 Eden 区的比值为 2:4。

11.双亲委派是什么?

当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class), 子类加载器才会尝试自己去加载。

采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object 对象

  • 24
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Retrograde-lx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值