JVM内存模型
- JVM内存模型包括哪些区域
- 答案:JVM内存模型主要包括以下区域:
- 程序计数器:是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节码指令的地址。
- Java虚拟机栈:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
- 本地方法栈:与Java虚拟机栈类似,不过它是为Native方法服务的。
- Java堆:是JVM所管理的内存中最大的一块,是被所有线程共享的一块内存区域,几乎所有的对象实例以及数组都在这里分配内存。
- 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在Java 8及之后版本中,永久代被移除,取而代之的是元空间,元空间并不在堆内存中,而是使用本地内存。
- 答案:JVM内存模型主要包括以下区域:
- 堆内存的结构是怎样的
- 答案:堆内存分为年轻代和老年代,年轻代又分为Eden空间和两个Survivor空间(一般称为Survivor from和Survivor to)。新创建的对象一般会先分配到Eden区,当Eden区满了之后,会触发Minor GC,存活下来的对象会被移动到Survivor区。在Survivor区经过多次GC后仍然存活的对象,会被移动到老年代。老年代主要存放生命周期较长的对象。
类加载机制
- 什么是类加载
- 答案:类加载是指将Java类的字节码文件(.class文件)转换成内存中运行时数据结构(如java.lang.Class对象)的过程。这个过程由Java虚拟机的类加载器完成,是Java动态性的基础。
- 类加载的时机有哪些
- 答案:Java虚拟机采用惰性加载策略,类会在以下几种情况下被加载:
- 创建类的实例,通过new关键字或反射机制。
- 访问类的静态变量或静态方法,注意是主动访问。
- 反射调用,如通过Class.forName()等方法显式加载类。
- 初始化类的子类,此时父类也会被加载(若尚未加载)。
- JVM启动时指定的主类,即包含main方法的类。
- 答案:Java虚拟机采用惰性加载策略,类会在以下几种情况下被加载:
GC算法
- GC有哪些常见的判定对象可回收的方法
- 答案:
- 引用计数法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1,当计数器为0时,就认为这个对象可以被回收。但这种方法存在循环引用的问题,导致对象无法被回收。
- 可达性分析算法:通过一系列的“GC Roots”对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,即可以被回收。
- 答案:
- GC的三种收集方法及其原理与特点
- 答案:
- 标记-清除算法:分为标记和清除两个阶段。首先标记出所有需要回收的对象,在标记完成后,统一回收所有被标记的对象。优点是实现简单,缺点是容易产生内存碎片,导致后续大对象无法分配内存。
- 复制算法:将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。优点是不会产生内存碎片,缺点是内存利用率低,只使用了一半的内存。
- 标记-压缩(标记-整理)算法:标记阶段和标记-清除算法一样,标记出所有需要回收的对象,清除阶段不是直接清理被标记的对象,而是将所有存活的对象向一端移动,然后直接清理掉边界以外的内存。优点是解决了内存碎片问题,同时内存利用率比复制算法高,缺点是移动对象时需要一定的开销。
- 答案:
垃圾回收器
- 常见的垃圾回收器有哪些
- 答案:常见的垃圾回收器有Serial、Serial Old、ParNew、Parallel Scavenge、Parallel Old、CMS、G1等。
- CMS收集器与G1收集器的特点
- 答案:
- CMS收集器:是一种以获取最短回收停顿时间为目标的收集器。采用“标记-清除”算法,具有并发收集、低停顿的特点,但是会产生内存碎片,并且对CPU资源非常敏感,在并发阶段会和用户线程抢占CPU资源。
- G1收集器:是一种面向堆内存任何部分进行回收的收集器,将堆内存划分为多个大小相等的独立区域(Region),可以预测停顿时间,兼具高吞吐量和低延迟的特点,采用“标记-整理”算法,不会产生内存碎片,能更好地处理大对象和巨型对象。
- 答案:
JVM线上调优
- 什么情况下需要进行JVM调优
- 答案:出现以下情况时通常需要进行JVM调优:
- Heap内存(老年代)持续上涨达到设置的最大内存值。
- Full GC次数频繁。
- GC停顿(Stop The World)时间过长(超过1秒,具体值按应用场景而定)。
- 应用出现OutOfMemory等内存异常。
- 应用中有使用本地缓存且占用大量内存空间。
- 系统吞吐量与响应性能不高或下降。
- 应用的CPU占用过高不下或内存占用过高不下。
- 答案:出现以下情况时通常需要进行JVM调优:
- JVM调优时关注哪些指标
- 答案:
- 吞吐量:用户代码时间/(用户代码执行时间+垃圾回收时间),吞吐量越高算法越好。
- 低延迟:STW越短,响应时间越好,暂停时间越短算法越好。
- Minor GC尽可能多的收集垃圾对象:遵守这一原则可以降低应用程序Full GC的发生频率,因为Full GC较耗时,可能会影响应用程序的延迟要求或吞吐量。
- 答案: