前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JVM 内存模型面试总结

JVM 内存模型面试总结

作者头像
Tim在路上
发布2020-08-04 23:29:46
5130
发布2020-08-04 23:29:46
举报
1. 什么是JVM?

就是 JAVA 虚拟机, 它只识别 .class 类型文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。

2. Java 代码的运行过程?

Java 源代码 -> 编辑器 -> 字节码文件

字节码 -> JVM -> 机器码文件

每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这也就是 Java 为什么能够 跨平台的原因

3. JVM后台常驻线程有?
  1. 虚拟机线程
  2. 周期任务线程
  3. Gc 线程
  4. 编辑器线程
  5. 信号分发线程
4. JVM内存区域分为?
  1. 私有区域 ,包括程序计数器,虚拟机栈,本地方法区
  2. 线程共享区,包括Java堆,方法区
  3. 直接内存

线程私有数据区域生命周期与线程相同, 依赖用户线程的启动/结束 而 创建/销毁(在 Hotspot VM 内

线程共享区域随虚拟机的启动/关闭而创建/销毁

运行时常量池(Runtime Constant Pool)是方法区的一部分。

5. 介绍下JAVA 虚拟机栈?

Java虚拟机栈是描述Java方法运行过程的内存模型。 Java虚拟机栈会为每一个即将运行的方法分配“栈帧”空间,用于保存改方法运行过程中所需要的一些信息,例如局部变量、操作数栈、动态链接、方法出口信息等。

Java虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。

局部变量表的创建是在方法被执行的时候,随着栈帧的创建而创建。而且,局部变量表的大小在编译时期就确定下来了,在创建的时候只需分配事先规定好的大小即可。

Java虚拟机栈会出现两种异常: StackOverFlowError OutOfMemoryError

StackOverFlowError:当线程请求栈的深度超过当前Java虚拟机栈的最大深度的时候,就抛出StackOverFlowError异常。

OutOfMemoryError: 若Java虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出OutOfMemoryError异常。

6. 介绍下JAVA 堆?

线程共享 :整个Java虚拟机只有一个堆,所有的线程都访问同一个堆。

在虚拟机启动时创建。 垃圾回收的主要场所。 不同的区域存放具有不同生命周期的对象。这样可以根据不同的区域使用不同的垃圾回收算法,从而更具有针对性,从而更高效。 堆的大小既可以固定也可以扩展,但主流的虚拟机堆的大小是可扩展的,因此当线程请求分配内存,但堆已满,且内存已满无法再扩展时,就抛出OutOfMemoryError。

7. 介绍下JAVA 方法区?

方法区中存放已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。

方法区是堆的一个逻辑部分,因此和堆一样,都是线程共享的。整个虚拟机中只有一个方法区。

方法区中的信息一般需要长期存在,而且它又是堆的逻辑分区,因此用堆的划分方法,我们把方法区称为老年代。

对方法区的内存回收的主要目标是:对常量池的回收 和 对类型的卸载。长期存在。

方法区中存放数据:类信息、常量、静态变量、即时编译器编译后的代码。其中常量存储在运行时常量池中。

常量池存在于方法区。

8. 从GC的角度,JAVA堆还可以怎么分?JVM运行时内存
  1. 新生代,包括Edan 区,From Survivor 和 To Survivior
  2. 老年代
  3. 永久代
9. 介绍一下新生代
  1. Edan区 :Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老 年代)。当 Eden区内存不够的时候就会触发 MinorGC,对新生代区进行 一次垃圾回收。
  2. Survivor From : 上一次 GC 的幸存者,作为这一次 GC 的被扫描者.
  3. Survivor To : 保留了一次 MinorGC 过程中的幸存者.
10. MinorGC 的过程?

复制 , 清空, 互换

MinorGC 采用复制算法。

1: eden、 servicorFrom 复制到 ServicorTo,年龄+1

首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年 龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不 够位置了就放到老年区);

2: 清空 eden、 servicorFrom

然后,清空 Eden 和 ServicorFrom 中的对象;

3: ServicorTo 和 ServicorFrom 互换

最后, ServicorTo 和 ServicorFrom 互换,原 ServicorTo 成为下一次 GC 时的 ServicorFrom 区。

11. 介绍下老年代和老年代的MajorGC?

老年代的对象比较稳定,所以 MajorGC 不会频繁执行。在进行 MajorGC 前一般都先进行 了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。

MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没 有标记的对象。 MajorGC 的耗时比较长,因为要扫描再回收。 MajorGC 会产生内存碎片,为了减 少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的 时候,就会抛出 OOM(Out of Memory)异常。

12. 介绍下永久代?

主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被 放入永久区域, 它和和存放实例的区域不同,GC 不会在主程序运行期对永久区域进行清理。所以这 也导致了永久代的区域会随着加载的 Class 的增多而胀满,最终抛出 OOM 异常。

当对象在 Survivor 区躲过一次 GC 后,其年龄就会+1。 默认情况下年龄到达 15 的对象会被 移到老生代中。

13. JAVA8 将永久代替换为元数据区

Java8 中, 永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间 的本质和永久代类似,

元空间与永久代之间最大的区别在于: 元空间并不在虚拟机中,而是使用本地内存。

因此,默认情况下,元空间的大小仅受本地内存限制。

14. GC 如何确定是垃圾?
  1. 引用计数法

在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单 的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关 联的引用, 即他们的引用计数都不为 0, 则说明对象不太可能再被用到,那么这个对象就是可回收 对象。

  1. 可达性分析

为了解决引用计数法的循环引用问题, Java 使用了可达性分析的方法。通过一系列的“GC roots” 对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的

不可达对象不等价于可回收对象, 不可达对象变为可回收对象至少要经过两次标记 过程。

15. JAVA中的四种引用类型?
  1. 强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即 使该对象以后永远都不会被用到 JVM 也不会回收。
  2. 软引用,用SoftReference实现,当系统内存足够时它 不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。
  3. 弱引用,弱引用需要用 WeakReference 类来实现,它比软引用的生存期更短,对于只有弱引用的对象 来说,只要垃圾回收机制一运行,不管 JVM 的内存空间是否足够,总会回收该对象占用的内存。
  4. 虚引用,虚引用需要 PhantomReference 类来实现,它不能单独使用,必须和引用队列联合使用。 虚 引用的主要作用是跟踪对象被垃圾回收的状态。
16. JAVA类加载机制?

JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化。

  1. 加载, 这个阶段会在内存中生成一个代表这个类的 java.lang.Class 作为方法区这个类的各种数据的入口。
  2. 验证,确保 Class文件的字节流中包含的信息是否符合当前虚拟机的要求
  3. 准备,是正式为类变量分配内存并设置类变量的初始值阶段,public static int v = 8080,实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080,但是如果声明的是常量就是8080,例如public static final int v = 8080。
  4. 解析,解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。
17. 什么是双亲委派机制?

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

18. CMS 收集器?

Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾 回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。 最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。 CMS工作机制相比其他的垃圾收集器来说更复杂,整个过程分为以下4个阶段:

  1. 初始标记 只是标记一下GC Roots能直接关联的对象,速度很快,仍然需要暂停所有的工作线程。
  2. 并发标记 进行GC Roots跟踪的过程,和用户线程一起工作,不需要暂停工作线程。
  3. 重新标记 为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记 记录,仍然需要暂停所有的工作线程。
  4. 并发清除 清除GC Roots不可达对象,和用户线程一起工作,不需要暂停工作线程。由于耗时最长的并 发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作,所以总体上来看 CMS收集器的内存回收和用户线程是一起并发地执行。
19. G1收集器?

Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与CMS 收集器,G1 收 集器两个最突出的改进是:

  1. 基于标记-整理算法,不产生内存碎片。
  2. 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。 G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域 的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾 最多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收 集效率。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 什么是JVM?
  • 2. Java 代码的运行过程?
  • 3. JVM后台常驻线程有?
  • 4. JVM内存区域分为?
  • 5. 介绍下JAVA 虚拟机栈?
  • 6. 介绍下JAVA 堆?
  • 7. 介绍下JAVA 方法区?
  • 8. 从GC的角度,JAVA堆还可以怎么分?JVM运行时内存
  • 9. 介绍一下新生代
  • 10. MinorGC 的过程?
    • 1: eden、 servicorFrom 复制到 ServicorTo,年龄+1
      • 2: 清空 eden、 servicorFrom
        • 3: ServicorTo 和 ServicorFrom 互换
        • 11. 介绍下老年代和老年代的MajorGC?
        • 12. 介绍下永久代?
        • 13. JAVA8 将永久代替换为元数据区
          • 元空间与永久代之间最大的区别在于: 元空间并不在虚拟机中,而是使用本地内存。
          • 14. GC 如何确定是垃圾?
          • 15. JAVA中的四种引用类型?
          • 16. JAVA类加载机制?
          • 17. 什么是双亲委派机制?
          • 18. CMS 收集器?
          • 19. G1收集器?
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档