1. 内存模型以及分区,需要详细到每个区放什么(共分为5个)。
- 程序计数器
- 程序计数器是每个线程私有的。
- 为了使每个线程在CPU线程切换后恢复到之前的程序执行位置。
- Java栈区
- 线程私有,生命周期与线程相同。
- 用于存放局部变量表、操作栈、动态链接和方法出口等。
- 每一个方法从被调用到被执行完,对应着一个栈帧在虚拟机中从入栈到出栈的过程。
- 会有SOF和OOM
- 本地方法栈
- 与java栈的作用和原理相似。
- Java栈为java方法服务,本地栈为执行本地方法服务。
- 堆区
- 被所有线程共享,用来存放对象实例。
- GC的主要区域
- 会有OOM
- 方法区
- 被所有线程共享。
- 用于存放已被JVM加载的类信息、常量、静态变量等数据。
1.1. GC机制
- GC主要管理的是堆区,堆区主要分为新生代和老年代
- 新生代,分为一个Eden和两个Survivor区,新new的对象都在这里,很快消亡。
- 老年代:新new的大对象直接丢到这里(为了避免在新生代区发生内存拷贝),其余是在新生代区多次回收没被干掉的变成老家伙的对象。
- 如何回收?
- 新生代:停止-复制算法
- 分为一个Eden区、两个Survivor区
- 先把Eden存活对象复制到Survivor0区,清空Eden区。
- 当Survivor0区满了以后,把Eden和Survivor0区的存活对象复制到Survivor1区,清空Eden区和Survivor0区
- 之后交换Survivor0和Survivor1区,保持Survivor1区是空的,如此往复。
- 老年代:标记清理、标记整理算法。
- 老年代存储的对象比年轻代多得多,而且不乏大对象,对老年代进行内存清理时,如果使用停止-复制算法,则相当低效
- 标记出仍然存活的对象(存在引用的),将所有存活的对象向一端移动,以保证内存的连续。再对其他标记不用的内存对象进行清理。
- 新生代:停止-复制算法
5. GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?
- 将转移到老年代的对象数量降到最少,可以调整新生代空间大小。
- 减少Full GC时间,将老年代空间设定为一个合适的值。
7. Minor GC与Full GC分别在什么时候发生?
- Minor GC触发条件
- 当Eden区满时,触发Minor GC
- Full GC触发条件
- 调用System.gc时,系统建议执行Full GC,但是不必然执行
- 老年代空间不足
- 方法区空间不足
- 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
9. 类加载的五个过程:加载、验证、准备、解析、初始化。
- 加载
- 通过一个类的权限定名来获取定义此类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法去的运行时数据结构
- 在java堆中生成一个代表这个类的java.lang.Class对象,作为方法去这些数据的访问入口。
- 验证
- 确保Class对象的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机的自身安全
- 准备
- 正式为类变量分配内存并设置类变量的初始值的阶段,这些内存都将在方法区中进行分配。
- 解析
- 虚拟机将常量池内的符号引用替换为直接引用的过程
- 初始化
- 执行类构造器<clinit>()方法的过程,这个阶段才真正开始执行类中定义的java程序代码