栈内存 问题 什么情况下会发生栈内存溢出。
思路 : 描述栈定义,再描述为什么会溢出,再说明一下相关配置参数,OK的话可以给面试官手写是一 个栈溢出的demo。
解 1.栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储 局部变量表,操作数栈,动态链接,方法出口等信息。局部变量表又包含基本数据类型,对象引用 类型 2.如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常,方法递 归调用产生这种结果。 3.如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是无法申请到足够的内存去完成 扩展,或者在新建立线程的时候没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将抛出一 个OutOfMemory 异常。(线程启动过多) 4.参数 -Xss 去调整JVM栈的大小
JVM内存模型 问题 详解JVM内存模型
思路 : 给面试官画一下JVM内存模型图,并描述每个模块的定义,作用,以及可能会存在的问题,如栈 溢出等。
解 程序计数器: 当前线程执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有 虚拟机栈: 存放基本数据类型,动态链接,方法出口,线程私有 Java堆: java内存最大的一块,所有对象实例、数组都存放在java堆,GC回收的地方,线程共享。 Native方法栈: 和虚拟栈相似,只不过它服务于Native方法,线程私有。 方法区: 存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据等。(即永久带), 回收目标主要是常量池的回收和类型的卸载,各线程共享
新生代,老年代,持久代(Eden和Survivor) 问题 JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么 要分为Eden和Survivor。
**思路:**先讲一下JAVA堆,新生代的划分,再谈谈它们之间的转化,相互之间一些参数的配置(如: – XX:NewRatio,–XX:SurvivorRatio等),再解释为什么要这样划分,最好加一点自己的理解。
解 如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被 填满,触发Major GC.老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC 长得多,所以需要分为Eden和Survivor。 d Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选 保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。 设置两个Survivor区最大的好处就是解决了碎片化,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满 了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续 的内存空间,避免了碎片化的发生)
GC流程 问题 JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代
思路: 先描述一下Java堆内存划分,再解释Minor GC,Major GC,full GC,描述它们之间转化流程。
解 Java堆 = 老年代 + 新生代 新生代 = Eden + S0 + S1 当 Eden 区的空间满了, Java虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor区。 大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)直接进入老年态; 如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。即长期存活的对象进入老年态。 老年代满了而无法容纳更多的对象,Minor GC 之后通常就会进行Full GC,Full GC 清理整个内存堆 – 包括年轻代和年老代。 Major GC 发生在老年代的GC,清理老年区,经常会伴随至少一次Minor GC,比Minor GC慢10倍以上。
垃圾收集器 问题 你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包 括原理,流程,优缺点。
思路: 一定要记住典型的垃圾收集器,尤其cms和G1,它们的原理与区别,涉及的垃圾回收算法。
解 Serial收集器: 单线程收集器,只会用一条收集垃圾线程去垃圾收集工作,重要的是他在收集垃圾时,会暂停所有正在进行的线程(STW),直到垃圾收集完毕。 新生代采用复制算法,老年代采用标记-整理算法。 它简单而高效(与其他收集器的单线程相比)。Serial收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率。 ParNew收集器: Serial收集器的多线程版本,使用多线程进行垃圾收集,其他行为均与Serial收集器一致,使用多线程进行垃圾收集。 新生代采用复制算法,老年代采用标记-整理算法。 它是许多运行在Server模式下的虚拟机的首要选择,除了Serial收集器外,只有它能与CMS收集器(真正意义上的并发收集器,后面会介绍到)配合工作。 Parallel Scavenge收集器: 它是许多运行在Server模式下的虚拟机的首要选择,除了Serial收集器外,只有它能与CMS收集器(真正意义上的并发收集器,后面会介绍到)配合工作。 Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。 新生代采用复制算法,老年代采用标记-整理算法。 CMS收集器: CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。标记-清除”算法实现 G1收集器: 2)CMS收集器和G1收集器的区别: CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用; G1收集器收集范围是老年代和新生代,不需要结合其他收集器使用; CMS收集器以最小的停顿时间为目标的收集器; G1收集器可预测垃圾回收的停顿时间 CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片 G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。