什么情况下会发生栈内存溢出

描述栈定义,再描述为什么会溢出,再说明一下相关配置参数,OK的话可以给面试官手写是一个栈溢出的demo。
  1. 栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。局部变量表又包含基本数据类型,对象引用类型
  2. 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常,方法递归调用产生这种结果
  3. 如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是无法申请到足够的内存去完成扩展,或者在新建立线程的时候没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将抛出一个OutOfMemory 异常。(线程启动过多)
  4. 参数 -Xss 去调整JVM栈的大小

详解JVM内存模型

思路: 给面试官画一下JVM内存模型图,并描述每个模块的定义,作用,以及可能会存在的问题,如栈溢出等。

image.png

  1. 程序计数器:当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有。
  2. Java虚拟栈:存放基本数据类型、对象的引用、方法出口等,线程私有。
  3. Native方法栈:和虚拟栈相似,只不过它服务于Native方法,线程私有。
  4. Java堆:java内存最大的一块,所有对象实例、数组都存放在java堆,GC回收的地方,线程共享。
  5. 方法区:存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。(即永久带),回收目标主要是常量池的回收和类型的卸载,各线程共享

JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和Survivor。

思路: 先讲一下JAVA堆,新生代的划分,再谈谈它们之间的转化,相互之间一些参数的配置(如: –XX:NewRatio,–XX:SurvivorRatio等),再解释为什么要这样划分,最好加一点自己的理解

共享内存区划分

  1. 共享内存区 = 持久带 + 堆
  2. 持久带 = 方法区 + 其他
  3. Java堆 = 老年代 + 新生代
  4. 新生代 = Eden + S0 + S1

一些参数的配置

  • 默认,新生代与老年代的比例的值是1:2,可以通过参数-XX:NewRatio配置。
  • 默认,Edem:from:to=8:1:1(可以通过参数-XX:SurvivorRatio来设定)
  • Survivor区中的对象被复制次数(对应虚拟机参数-XX:+MaxTenuringThreshold)

为什么要分为Eden和Survivor?为什么要设置两个Survivor区?

  1. 如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC.老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多,所以需要分为Eden和Survivor。
  2. Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有尽力了16次Minor GC还能在新生代中存活的对象,才会被送到老年代。
  3. 设置两个Survior区最大的好处就是解决了碎片化,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移到到第一块survivor space S0,Eden被清空;等Eden区在满了,就再触发一次Minor GC,Eden和S0中的存活对象又被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了s1中来自S0和Eden两部分的存活对象占有连续的内存空间,避免了碎片化的发生。)

JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代

思路:先描述一下Java堆内存划分,再解释Minor GC、Major GC、full GC、以及他们之间的转化流程
  1. Java堆 = 老年代 + 新生代
  2. 新生代 = Eden + S0 + S1
  3. 当Eden区的空间满了,Java虚拟机会触发一次Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到Survivor区。
  4. 大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)则直接进入老年态。
  5. 如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。即上期存活的指向进入老年态。
  6. 老年代满了而无法容纳更多的对象,Minor GC之后通常就进行Full GC,Full GC清理整个内存堆-包括年轻代和年老代。
  7. Major Gc发生在老年代的GC,清理老年区,经常会伴随至少一次Minor GC,比Minor GC慢10倍以上。

你知道哪几种垃圾收集器,各自的优缺点,重点讲下CMS和G1,包括原理,流程,优缺点

思路: 一定要记住典型的垃圾收集器,尤其cms和G1,它们的原理与区别,涉及的垃圾回收算法。

几种垃圾收集器

  1. Serial收集器: 单线程的收集器,收集垃圾时,必须stop the world,使用复制算法。
  2. ParNew收集器: Serial收集器的多线程版本,也需要stop the world,复制算法
  3. Parallel Scavenge收集器: 新生代收集器,复制算法的收集器,并发的多线程收集器,目标是达到一个可控的吞吐量。如果虚拟机总共运行100分钟,其中垃圾花掉1分钟,吞吐量就是99%。

李博帅
15 声望4 粉丝