【JVM 深入了解】JVM 到底包含什么?

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主

⛪️ 个人社区:个人社区

💞 个人主页:个人主页

🙉 专栏地址: ✅ Java 中级

🙉八股文专题:剑指大厂,手撕 Java 八股文

文章目录

      • [1. JVM 架构](#1. JVM 架构)
      • [2. 垃圾收集机制](#2. 垃圾收集机制)
      • [3. 性能优化](#3. 性能优化)
      • [4. 内存模型](#4. 内存模型)
      • [5. 类加载过程](#5. 类加载过程)
      • [6. 字节码执行](#6. 字节码执行)
      • [7. 常见问题与调试](#7. 常见问题与调试)
      • [8. 最佳实践](#8. 最佳实践)

Java 虚拟机(JVM, Java Virtual Machine)是 Java 平台的核心组件,它负责执行 Java 字节码。JVM 提供了一个跨平台的运行环境,使得 Java 程序可以在不同的操作系统上运行而无需重新编译。以下是关于 JVM 的一些关键内容:

1. JVM 架构

JVM 主要由以下几个部分组成:

  • 类加载器子系统(Class Loader Subsystem)

    • 引导类加载器(Bootstrap Class Loader) :加载核心 Java 类库(如 java.lang.*)。
    • 扩展类加载器(Extension Class Loader) :加载 Java 扩展库(位于 jre/lib/ext 目录下的类库)。
    • 应用程序类加载器(Application Class Loader):加载用户自定义的应用程序类。
  • 运行时数据区(Runtime Data Area)

    • 方法区(Method Area):存储类的结构信息,如运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容等。
    • 堆(Heap):存储对象实例和数组。堆是所有线程共享的内存区域。
    • 虚拟机栈(VM Stack):每个线程都有一个私有的虚拟机栈,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
    • 本地方法栈(Native Method Stack):与虚拟机栈类似,但为本地方法服务。
    • 程序计数器(Program Counter Register):记录当前线程所执行的字节码指令地址。
  • 执行引擎(Execution Engine)

    • 解释器(Interpreter):逐条解释并执行字节码。
    • 即时编译器(Just-In-Time Compiler, JIT):将热点代码编译成本地机器码,提高执行效率。
    • 垃圾收集器(Garbage Collector, GC):自动管理内存,回收不再使用的对象。
    • 本地接口(Native Interface):与本地方法库交互,调用本地方法。
  • 本地方法库(Native Method Libraries)

    • 包含了特定平台相关的本地方法实现,如文件 I/O、网络通信等。

2. 垃圾收集机制

JVM 的垃圾收集机制主要负责自动管理内存,回收不再使用的对象。常见的垃圾收集算法包括:

  • 标记-清除(Mark and Sweep)

    • 标记阶段:从根集合开始遍历,标记所有可达的对象。
    • 清除阶段:回收未被标记的对象。
  • 复制(Copying)

    • 将存活对象从一个空间复制到另一个空间,然后清空原来的内存空间。
  • 标记-整理(Mark and Compact)

    • 标记阶段:标记所有可达的对象。
    • 整理阶段:将存活对象向一端移动,然后清理边界外的内存。
  • 分代收集(Generational Collection)

    • 将堆分为新生代(Young Generation)和老年代(Old Generation),针对不同代采用不同的收集策略。
    • 新生代通常使用复制算法,老年代通常使用标记-整理或标记-清除算法。

3. 性能优化

  • JIT 编译器

    • 通过将热点代码编译成本地机器码,提高执行效率。
    • 可以通过 -XX:CompileThreshold 参数调整触发 JIT 编译的阈值。
  • 垃圾收集器选择

    • 不同的垃圾收集器适用于不同的场景,如 Serial GC、Parallel GC、CMS GC 和 G1 GC。
    • 可以通过 -XX:+UseSerialGC-XX:+UseParallelGC-XX:+UseConcMarkSweepGC-XX:+UseG1GC 等参数选择合适的垃圾收集器。
  • 堆大小设置

    • 通过 -Xms-Xmx 参数设置初始堆大小和最大堆大小。
    • 合理设置堆大小可以避免频繁的垃圾收集和 OutOfMemoryError。
  • 其他优化参数

    • -XX:NewRatio:设置新生代和老年代的比例。
    • -XX:SurvivorRatio:设置 Eden 区和 Survivor 区的比例。
    • -XX:MaxTenuringThreshold:设置晋升老年代的最大年龄。
    • -XX:ParallelGCThreads:设置并行垃圾收集的线程数。

4. 内存模型

JVM 的内存模型规定了多线程环境下对共享变量的访问规则,主要包括:

  • 主内存与工作内存

    • 每个线程都有自己的工作内存,存储了该线程读写共享变量的副本。
    • 主内存中存储了所有的共享变量。
  • 原子性、可见性和有序性

    • 原子性:保证基本数据类型的读写操作是原子的。
    • 可见性:确保一个线程对共享变量的修改对其他线程是可见的。
    • 有序性:禁止编译器和处理器对指令进行重排序。
  • volatile 关键字

    • 保证变量的可见性和有序性。
    • 防止指令重排序。
  • synchronized 关键字

    • 保证代码块的原子性和可见性。
    • 通过监视器锁(Monitor Lock)实现互斥访问。

5. 类加载过程

类加载过程主要包括以下步骤:

  • 加载(Loading)

    • 通过类的全限定名获取二进制流。
    • 将二进制流转换为方法区内的运行时数据结构。
    • 在内存中生成一个代表这个类的 java.lang.Class 对象。
  • 验证(Verification)

    • 确保被加载的类符合 JVM 规范,防止恶意代码破坏 JVM 安全。
  • 准备(Preparation)

    • 为类的静态变量分配内存,并设置默认初始值。
  • 解析(Resolution)

    • 将符号引用替换为直接引用。
  • 初始化(Initialization)

    • 执行类构造器 <clinit>() 方法,初始化静态变量和静态代码块。

6. 字节码执行

  • 字节码

    • Java 源代码经过编译后生成的中间表示形式。
    • 字节码是一种平台无关的二进制格式。
  • 解释执行

    • 解释器逐条解释并执行字节码。
  • 即时编译

    • JIT 编译器将热点代码编译成本地机器码,提高执行效率。

7. 常见问题与调试

  • OutOfMemoryError

    • 堆内存溢出(Heap Space):增加堆内存大小。
    • 栈内存溢出(Stack Overflow):检查递归调用深度。
    • 方法区内存溢出(PermGen 或 Metaspace):增加方法区大小。
  • 性能监控工具

    • JConsole:图形化监控工具,可以查看 JVM 的内存使用情况、线程状态等。
    • VisualVM:更强大的图形化监控工具,支持性能分析、内存快照等功能。
    • jstat:命令行工具,用于监控 JVM 的性能统计信息。
    • jmap:命令行工具,用于生成堆转储快照。
    • jstack:命令行工具,用于打印线程堆栈跟踪信息。

8. 最佳实践

  • 合理设置堆大小

    • 根据应用的实际需求设置 -Xms-Xmx,避免频繁的垃圾收集。
  • 选择合适的垃圾收集器

    • 根据应用的特点选择适合的垃圾收集器,如低延迟应用可以选择 G1 GC。
  • 减少不必要的对象创建

    • 使用对象池、缓存等技术减少对象的创建和销毁。
  • 使用并发编程

    • 利用多线程提高应用的并发处理能力,但要注意线程安全问题。
  • 定期进行性能分析

    • 使用性能监控工具定期分析应用的性能瓶颈,进行针对性优化。

JVM 是 Java 应用程序运行的基础,理解 JVM 的架构、垃圾收集机制、性能优化、内存模型、类加载过程等内容对于开发高性能、可靠的 Java 应用至关重要。通过合理的配置和最佳实践,可以显著提升应用的性能和稳定性。

精彩专栏推荐订阅:在下方专栏👇🏻
2023年华为OD机试真题(A卷&B卷)+ 面试指导
精选100套 Java 项目案例
面试需要避开的坑(活动)
你找不到的核心代码
带你手撕 Spring
Java 初阶

相关推荐
2401_8532757323 分钟前
Java IO 基础知识总结下
java·开发语言
我想睡到自然醒₍˄·͈༝·͈˄*₎◞ ̑27 分钟前
【Android】View的解析—滑动篇
android·java
诸神黄昏EX29 分钟前
Android 常用命令和工具解析之内存相关
android·java·开发语言
dreamsever38 分钟前
Glide源码学习
android·java·学习·glide
武昌库里写JAVA39 分钟前
SpringBoot+SpringCloud面试题整理附答案
java·开发语言·算法·spring·log4j
呼啦啦啦啦啦啦啦啦43 分钟前
每日刷题(有效括号序列,滑动窗口最大值,最小的K个数,寻找第K大)
java·前端·javascript
手握风云-1 小时前
数据结构(Java版)第五期:ArrayList与顺序表(下)
java·数据结构·算法
蜗牛沐雨1 小时前
Go语言中的sync.Pool详解:高效对象复用
java·jvm·golang
不会玩技术的技术girl1 小时前
Java爬虫与淘宝API接口:深度解析销量和商品详情数据获取
java·开发语言·爬虫
MG_鹏鹏1 小时前
SpringBoot实现单文件上传
java·spring boot·spring