wap网站使用微信登陆,服务器网站备案,易企网络网站建设,珠海建设工程交易中心网站JVM部分[2025/1/13 ~ 2025/1/19] 1. JVM 由哪些部分组成#xff1f;2. Java 的类加载过程是怎样的#xff1f;3. 请你介绍下 JVM 内存模型#xff0c;分为哪些区域#xff1f;各区域的作用是什么#xff1f;4. JVM 垃圾回收调优的主要目标是什么#xff1f;5. 如何对 Jav… JVM部分[2025/1/13 ~ 2025/1/19] 1. JVM 由哪些部分组成2. Java 的类加载过程是怎样的3. 请你介绍下 JVM 内存模型分为哪些区域各区域的作用是什么4. JVM 垃圾回收调优的主要目标是什么5. 如何对 Java 的垃圾回收进行调优6. 常用的 JVM 配置参数有哪些7. Java 中常见的垃圾收集器有哪些8. 垃圾收集算法9. 线上 CPU 飙高如何排查10. 怎么分析 JVM 当前的内存占用情况11. OOM 后怎么分析 我的博客地址
1. JVM 由哪些部分组成
组成 类加载器子系统ClassLoader运行时数据区Runtime Data Area执行引擎Execution Engine本地方法接口Native InterfaceJNI 执行流程 首先需要准备编译好的 Java 字节码文件即class文件。 然后需要先通过一定方式类加载器将 class 文件加载到内存中运行时数据区。 又因为字节码文件是 JVM 定义的一套指令集规范底层操作系统无法直接执行。 因此需要特定的命令解释器执行引擎将字节码翻译成特定的操作系统指令集交给 CPU 去执行。 这个过程中会需要调用到一些不同语言为 Java 提供的接口例如驱动、地图制作等这就用到了本地方法接口Native Interface。
2. Java 的类加载过程是怎样的
加载: 将二进制流读入内存中为了生成一个 Class 对象。链接 a. 验证: 主要是验证加载进来的二进制流是否符合一定格式是否规范是否符合当前 JVM 版本等等之类的验证。 b. 准备: 为静态变量(类变量)赋初始值也即为它们在方法区划分内存空间。这里注意是静态变量并且是初始值比如 int 的初始值是 0。 c. 解析: 将常量池的符号引用转化成直接引用。 符号引用可以理解为只是个替代的标签比如你此时要做一个计划暂时还没有人选你设定了个 A 去做这个事。然后等计划真的要落地的时候肯定要找到确定的人选到时候就是小明去做一件事。解析就是把 A(符号引用) 替换成小明(直接引用)。符号引用就是一个字面量没有什么实质性的意义只是一个代表。 直接引用指的是一个真实引用在内存中可以通过这个引用查找到目标。 初始化: 这时候就执行一些静态代码块为静态变量赋值这里的赋值才是代码里面的赋值准备阶段只是设置初始值占个坑。
3. 请你介绍下 JVM 内存模型分为哪些区域各区域的作用是什么
程序计数器Program Counter Register每个线程都有自己的程序计数器用于指示当前线程执行的字节码指令的行号以便线程执行时能够回到正确的位置。虚拟机栈JVM Stack也称为 Java 方法栈用于存储方法执行时的局部变量表、操作数栈、动态链接、方法出口等信息。每个线程在执行一个方法时都会为该方法分配一个栈帧并将该栈帧压入虚拟机栈当方法执行完毕后虚拟机会将其出栈。本地方法栈Native Method Stack与虚拟机栈类似用于存储本地方法的执行信息。堆Heap用于存放所有线程共享的对象和数组是垃圾回收的主要区域。方法区Method Area用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也是被所有线程共享的。方法区具体实现永久代/元空间 程序计数器、虚拟机栈、本地方法栈是线程私有的堆、方法区、运行时常量池是线程共享的。 4. JVM 垃圾回收调优的主要目标是什么 GC 调优的核心思路就是尽可能的使对象在年轻代被回收减少对象进入老年代。 吞吐量调优主要关注降低垃圾回收的总时间通过 Parallel Scavenge 和 Parallel Old 提高 CPU 使用效率。延迟调优关注最大停顿时间通过 CMS、G1、ZGC 等收集器降低 STW 停顿时间。堆大小调优通过合理的堆内存分配和分代比例调优避免频繁的 Minor GC 和 Full GC。
5. 如何对 Java 的垃圾回收进行调优
思路 分析Young GC 和 Full GC 触发频率、原因、晋升的速率、老年代内存占用量, 可以使用命令(jstat -gc [pid] [频率] [总次数])或监控页面查看 例如: 如果发现频繁会产生 Full GC分析日志之后发现没有内存泄漏只是 Young GC 之后会有大量的对象进入老年代然后最终触发 Ful GC。所以就能得知是 Survivor 空间设置太小导致对象过早进入老年代因此调大 Survivor 。
6. 常用的 JVM 配置参数有哪些
-Xms初始化堆内存大小-Xmx最大堆内存大小-Xss设置每个线程的栈大小-XX:MetaspaceSize初始化元空间大小-XX:MaxMetaspaceSize最大元空间大小-XX:HeapDumpOnOutOfMemoryError当发生 OutOfMemoryError 时生成堆转储heap dump文件-XX:HeapDumpPath: 生成堆转储文件路径-XX:PrintGCDetails打印详细的垃圾回收日志-XX:UseG1GC启用G1垃圾收集器-XX:UseConcMarkSweepGC启用CMS垃圾收集器-XX:UseZGC启用ZGC低延迟垃圾收集器
7. Java 中常见的垃圾收集器有哪些
新生代垃圾收集器 1Serial 收集器 单线程收集器适合小型应用和单处理器环境。触发 Stop-The-WorldSTW操作所有应用线程在 GC 时暂停。适用场景适用于单线程应用和客户端模式。 2ParNew 收集器 是 Serial 收集器的多线程版本能够并行进行垃圾收集。与 CMS 收集器配合使用时通常会选择 ParNew 收集器作为新生代收集器。适用场景适用于多处理器环境通常配合 CMS 收集器使用。 3Parallel Scavenge 收集器吞吐量优先 也称为 “吞吐量收集器”追求最大化 CPU 时间的利用率。并行处理新生代垃圾回收适合大规模后台任务处理注重吞吐量而非延迟。适用场景适用于大规模运算密集型后台任务适合对吞吐量要求较高的场景。 老年代垃圾收集器 1Serial Old 收集器 Serial 收集器的老年代版本使用标记-整理Mark-Compact算法进行垃圾回收。适用场景适合单线程环境和低内存使用场景通常配合 Serial 收集器一起使用。 2Parallel Old 收集器 Parallel Scavenge 收集器的老年代版本使用多线程并行标记-整理算法。适用场景适合大规模并行计算的场景适用于高吞吐量要求的任务。 3CMSConcurrent Mark-Sweep收集器 并发标记-清除收集器追求低延迟减少 GC 停顿时间。使用并发标记和清除算法适合对响应时间有较高要求的应用。缺点可能会产生内存碎片并且在并发阶段可能会发生 Concurrent Mode Failure导致 Full GC。适用场景适用于对响应时间要求高的应用如 Web 服务和电商平台。 4G1Garbage First收集器 年轻代采用类似于传统的复制算法, 老年代采用标记整理算法设计用于取代 CMS 的低延迟垃圾收集器能够提供可预测的停顿时间。通过分区来管理内存并在垃圾收集时优先处理最有价值的区域避免了 CMS 的内存碎片问题。适用场景适合大内存、多 CPU 服务器应用尤其在延迟和响应时间敏感的场景中表现出色。 5ZGCZ Garbage Collector收集器 低停顿、高吞吐量的垃圾收集器停顿时间一般不会超过 10 毫秒。适用场景适用于需要管理大堆内存且对低延迟要求极高的应用。
8. 垃圾收集算法
标记-清除算法Mark-Sweep 主要用于 CMS标记存活对象后清除不可达对象但容易产生内存碎片。工作原理首先遍历堆中的对象标记出所有的存活对象接着清除未标记的对象。优点实现简单能够处理堆中的所有对象。缺点标记和清除的过程会产生内存碎片影响后续内存分配的效率。 标记-整理算法Mark-Compact 用于 G1 和 Parallel Old标记存活对象后进行整理避免内存碎片。工作原理首先标记出所有存活的对象然后将存活的对象整理到一边最后清除未标记的对象。优点避免了内存碎片问题。缺点整理阶段需要移动对象会导致额外的开销。 复制算法Copying 工作原理将内存分成两部分每次只使用其中一半垃圾回收时将存活的对象从一半复制到另一半清除原区域的所有对象朴素的复制算法是这样的实际使用会分为两个 survivor 和一个 eden 区。优点无需处理内存碎片分配效率高。缺点需要双倍的内存空间浪费了一半的空间。
9. 线上 CPU 飙高如何排查
首先确认哪个进程占用 CPU 过高登录服务器利用 top 命令查看。 top 命令是 Linux 下常用的性能分析工具能够实时显示系统中各个进程的资源占用状况类似于 Windows 的任务管理器确认 CPU 利用率很高的进程的 PID假设为 1234 确实是 Java 进程则通过 top -Hp 1234 查看具体的线程。假设得到的线程 ID 是 5678再将线程转为十六进制。可以使用 printf %x\n 5678得到十六进制的 tid 为 162e此时在利用 jstack 1234 | grep 162e -A 100 查看具体的栈信息。根据堆栈信息就可以定位到具体是哪行代码导致了 CPU 飙高对应分析修复即可
10. 怎么分析 JVM 当前的内存占用情况
利用 jstat 监控和分析 JVM 内部的垃圾回收、内存等运行状态。可以用它来查看堆内存、非堆内存等的实时状态。使用命令 jstat -gc [pid] [频率] [总次数]可以使用 jmap 查看 JVM 堆的详细信息包括堆的配置、内存使用情况、GC 活动等。\阿里 arthas 使用 dashboard: 可以查看当前系统的实时数据面板。数据面板默认5秒刷新一次。可以 输入Q 后回车 或 CtrlC 退出dashboard命令。thread: 后面加上线程ID会打印线程的栈。Arthas支持管道可以用 thread 1 | grep ‘main(’ 查找到arthas-demo应用的main class。sc: 用来查找JVM里已加载的类。例如查看名称为MathGame的类sc -d *MathGamejad: 用来反编译代码 。例如查看MathGame类的源代码jad demo.MathGamewatch: 可以查看函数的参数/返回值/异常信息。例如查看MathGame类中primeFactors函数的返回值watch demo.MathGame primeFactors returnObj 每次函数被调用都会打印返回值可以 输入Q 后回车 或 CtrlC 退出watch命令。
11. OOM 后怎么分析 在发生 OOM 时可以根据 jmap 得到堆转储文件建议增加JVM启动参数-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/tmp/heapdump.hprof在发生 OOM 后自动生成转储文件再导入到 MAT、VisualVM、GCeasy等工具中分析文件找出哪些对象占用了大量的内存再定位到具体的代码解决问题。 OOM内存泄露常见问题:
堆内存溢出Java Heap Space Java 堆用于存放对象实例如果创建了过多对象或有内存泄漏导致对象无法被垃圾回收堆内存就会耗尽。 如果有大量创建对象或集合类的场景持续增加数据但未释放就会产生堆内存溢出。错误信息java.lang.OutOfMemoryError: Java heap space解决方法检查对象创建逻辑确保及时释放无用对象或增大堆内存大小-Xmx 参数。 栈内存溢出StackOverflowError 每个线程都有独立的栈空间栈用于存储方法调用的信息局部变量、方法参数、返回地址等。如果方法调用层次过深或存在无限递归栈空间耗尽就会导致栈溢出。 常见于递归方法没有正确的退出条件、深层嵌套的方法调用场景。错误信息java.lang.StackOverflowError解决方法检查递归条件优化递归算法或增加栈空间-Xss 参数。 方法区或元空间溢出Metaspace / PermGen space 在 Java 8 之前方法区被实现为永久代PermGen用于存放类的元数据类信息、方法信息、常量池等。在 Java 8 之后永久代被替换为元空间Metaspace用本地内存实现。在频繁加载和卸载类的情况下如使用大量动态生成的代理类或频繁热部署可能导致方法区或元空间溢出。常见于使用动态代理频繁生成类、大量反射调用或频繁热部署场景。错误信息 Java 7 及之前java.lang.OutOfMemoryError: PermGen spaceJava 8 及之后java.lang.OutOfMemoryError: Metaspace解决方法增加元空间大小-XX:MaxMetaspaceSize优化代码以减少类加载和反射的频率。 直接内存溢出Direct Buffer Memory Java NIO 使用直接内存Direct Memory来加快 I/O 操作该内存不受 JVM 堆内存的限制。如果分配过多的直接内存超过了设置的最大值也会导致内存溢出。 常见于使用 NIO 操作 ByteBuffer 分配大量直接内存或者 Netty 等框架中频繁使用直接内存场景。错误信息java.lang.OutOfMemoryError: Direct buffer memory解决方法检查直接内存的分配和释放情况增加直接内存大小限制-XX:MaxDirectMemorySize或避免过多使用直接内存。 线程数过多导致的内存溢出Unable to Create New Native Thread 每个线程都需要栈空间和一定的操作系统资源。如果创建过多线程而超出操作系统的资源限制可能无法再创建新的线程导致 OOM。 常见于创建大量线程或线程池大小过大。错误信息java.lang.OutOfMemoryError: Unable to create new native thread解决方法减少线程数合理设置线程池的大小避免无限制地创建新线程。 GC 执行耗时过长导致的 OOMGC Overhead Limit Exceeded 当 JVM 在垃圾回收上花费的时间过多且回收的内存不足以满足需要JVM 会抛出 GC Overhead Limit Exceeded 错误以避免长时间的垃圾回收循环。通常发生在堆内存接近耗尽但又无法完全释放的情况下。常见于对象频繁创建和销毁导致 GC 频繁触发内存不足导致 GC 效率低下场景。错误信息java.lang.OutOfMemoryError: GC overhead limit exceeded解决方法增大堆内存优化代码以减少短生命周期对象的创建或调整垃圾回收策略。