1.什么情况下会发生栈内存溢出。
描述栈定义,再描述为什么会溢出,再说明一下相关配置参数,OK的话可以给面试官手写是一个栈溢出的demo。
java栈:Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表、操作数栈等等。当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。
- 使用-Xss参数减少栈内存容量。
- 定义了大量的本地变量,增大此方法帧中本地变量表的长度。
2.详解JVM内存模型
思路: 给面试官画一下JVM内存模型图,并描述每个模块的定义,作用,以及可能会存在的问题,如栈溢出等。
- 程序计数器(PC寄存器):为了能够使得每个线程都在线程切换后能够恢复在切 换 之前的程序执行位置,每个线程都需要有自己独立的程序计数器,并且不能互相被干扰。不会发生内存溢出现象的。
- java栈:Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表、操作数栈等等。当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。
- 本地方法栈:本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法服务的
- 堆:Java中的堆是用来存储对象本身的以及数组(数组引用是存放在Java栈中的)。堆是被所有线程共享的,在JVM中只有一个堆。
- 方法区:是被线程共享的区域。在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码,运行时常量池等。
方法区,堆,栈,本地方法栈都会产生内存溢出,后两者是在多线程情况下。并且在单线程情况下还会产生栈溢出
3.JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和Survivor。
思路: 先讲一下JAVA堆,新生代的划分,再谈谈它们之间的转化,相互之间一些参数的配置(如: –XX:NewRatio,–XX:SurvivorRatio等),再解释为什么要这样划分,最好加一点自己的理解。)共享内存区划分
首先:java堆分为新生代,老年代,元空间。其中新生代分为Eden和FromSurvivor和ToSrvivor。比例为8:1:1.
- 当新生代中发生Minor GC时,
- 把 Eden + From Survivor 存活的对象放入 To Survivor 区;
- 清空 Eden 和 From Survivor 分区;
- From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。
- 每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。
4.JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代
思路: 先描述一下Java堆内存划分,再解释Minor GC,Major GC,full GC,描述它们之间转化流程。
新生代默认的空间占比总空间的 1/3,老年代的默认占比是 2/3。
多数情况,对象都在新生代 Eden 区分配。当 Eden 区分配没有足够的空间进行分配时,虚拟机将会发起一次 Minor GC。如果本次 GC 后还是没有足够的空间,则将启用分配担保机制在老年代中分配内存。
Minor GC 是指发生在新生代的 GC,因为 Java 对象大多都是朝生夕死,所有 Minor GC 非常频繁,一般回收速度也非常快;
Major GC/Full GC 是指发生在老年代的 GC,出现了 Major GC 通常会伴随至少一次 Minor GC。Major GC 的速度通常会比 Minor GC 慢 10 倍以上。
5.你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包括原理,流程,优缺点。
思路: 一定要记住典型的垃圾收集器,尤其cms和G1,它们的原理与区别,涉及的垃圾回收算法。
CMS:以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。基于并发“标记清理”实现CMS收集器采用增量更新算法实现(并发收集,低停顿)(对CPU非常敏感,无法处理浮动垃圾,CMS使用“标记-清除”法会产生大量的空间碎片)
G1:是一款面向服务端应用的垃圾收集器G1 收集器则是通过原始快照(SATB)算法来实现的(并行于并发,分代收集,空间整合,可预测的停顿)(有时候延时停顿可能没cms好)
cms 初始标记-并发标记-重新标记-并发处理
g1:初始标记-并发标记-最终标记-筛选回收
6.什么是内存屏障
内存屏障是插入两个CPU命令之间的命令,禁止处理器命令的重新排序(如屏障),以确保有序性。此外,为了达到屏障的效果,在处理器写入、读取值之前,将主机的值写入缓存,清空无效的队列,保障可见性。
7.强引用、软引用、弱引用、虚引用的区别?
先说一下四种引用的定义,可以结合代码讲一下,也可以扩展谈到ThreadLocalMap里弱引用用处。
- 强引用:发生 gc 的时候不会被回收。
- 软引用:有用但并不是必需的对象,在对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。
- 弱引用:非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象
- 虚引用:无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc时返回一个通知。
8.对象创建过程
- 类加载
- 分内存
- 并发
- 初始化
9.为对象分配内存的方式
- 指针碰撞
- 空闲列表
10 说一下 JVM 有哪些垃圾回收算法?
标记-清除算法
标记-复制算法
标记-整理算法
分代收集算法