JVM简介

发布于:2025-06-05 ⋅ 阅读:(27) ⋅ 点赞:(0)
  1. JAVA内存模型

以下是关于 Java内存模型(JMM) 的核心要点总结:

一、JMM的核心作用

Java内存模型是 **多线程环境下内存访问的规范**,主要解决以下问题:

  1. 可见性:线程对共享变量的修改对其他线程立即可见(避免CPU缓存不一致)。

  2. 原子性:确保指令执行不受线程切换影响(如volatilesynchronized或原子类)。

  3. 有序性:防止CPU指令重排序(通过内存屏障实现)。

二、JMM的内存结构

组件

作用

主内存

存储所有共享变量(线程间可见)。

工作内存

线程私有,存储主内存变量的副本(操作完成后同步回主内存)。

三、关键实现机制

  1. 内存屏障分为LoadLoadStoreStoreLoadStoreStoreLoad四类,用于禁止特定类型的指令重排序。

  2. happens-before规则保证操作的顺序性,例如:

    1. 程序顺序规则

    2. volatile变量的写操作优先于读操作

    3. 锁的释放优先于获取

  3. volatile关键字

    1. 强制从主内存读写变量,禁用缓存优化。

    2. 禁止指令重排序(类似内存屏障)。

四、并发编程实践

场景

解决方案

线程安全计数器

使用AtomicIntegerLongAdder(原子性+可见性)。

单例模式

双重检查锁中需用volatile修饰实例(防止指令重排序)。

状态标志控制

volatile boolean替代锁(轻量级可见性保障)。

五、JMM与JVM内存模型的区别

对比维度

JMM

JVM内存模型

定位

多线程内存访问规范

物理内存区域划分(堆、栈等)

核心问题

可见性、原子性、有序性

内存分配与垃圾回收

典型工具

volatilesynchronized、原子类

JVM参数调优(-Xmx-Xss等)

六、调优工具推荐

  1. MAT(Memory Analyzer Tool):分析堆转储,定位内存泄漏。

  2. JFR(Java Flight Recorder):实时监控内存分配与GC事件。

  3. Arthas:在线诊断线程状态(如thread -n 3查CPU占用、方法执行耗时)。

七、线程上下文切换

Java内存模型(Java Memory Model, JMM)和线程上下文切换之间有着密切的关系。理解这两者的关系有助于编写高效且线程安全的并发程序。

Java内存模型(JMM)

Java内存模型定义了Java程序中变量(包括实例字段、静态字段和构成数组对象的元素)的访问规则。它描述了在多线程环境下,变量的值如何在不同线程之间传递。JMM的主要目标是提供一种机制,使得程序员可以在多线程环境下编写正确的并发程序。

JMM的核心概念包括:

  • 主内存和工作内存:每个线程都有自己的工作内存,工作内存保存了该线程使用到的变量的副本。主内存是所有线程共享的内存区域。

  • 内存可见性:JMM规定了一个线程对变量的写入何时对另一个线程可见。

  • volatile关键字:保证变量的可见性和有序性。

  • synchronized关键字:保证代码块的原子性和可见性。

线程上下文切换

线程上下文切换是指CPU从一个线程切换到另一个线程的过程。上下文切换涉及保存和恢复线程的状态,包括程序计数器、寄存器和变量等。上下文切换是多线程环境下实现并发的基础,但频繁的上下文切换会带来性能开销。

JMM与线程上下文切换的关系

  1. 内存可见性:在多线程环境下,线程上下文切换可能导致内存可见性问题。一个线程对变量的修改在另一个线程中可能不可见。JMM通过定义内存屏障和happens-before关系来解决这个问题,确保线程之间的内存可见性。

  1. 缓存一致性:线程上下文切换时,线程的工作内存(缓存)需要与主内存保持一致。JMM通过规定变量的读取和写入规则,确保线程切换后,变量的一致性。

  1. 指令重排序:为了提高性能,编译器和处理器可能会对指令进行重排序。JMM通过内存屏障和happens-before关系,限制了重排序的范围,确保多线程程序的正确性。

  1. 同步机制:JMM提供的同步机制(如volatile和synchronized)在线程上下文切换时起到了关键作用。它们确保了线程切换时的内存可见性和操作的原子性。

总结

Java内存模型和线程上下文切换共同作用,确保了多线程环境下程序的正确性和性能。理解JMM的工作原理和线程上下文切换的机制,有助于编写高效且线程安全的并发程序。

总结

掌握JMM是编写 高效且线程安全 的Java程序的关键。理解其底层原理(如内存屏障、happens-before规则)能有效避免并发陷阱(如死锁、数据竞争),结合工具可快速定位性能瓶颈。

  1. JVM内存模型

一、JVM内存区域划分

JVM内存模型主要分为线程共享区域线程私有区域

  1. 线程共享区域

    1. 堆(Heap)

      • 存储所有对象实例和数组(约80%对象在此分配)。

      • 细分结构:

        • 新生代(Young Generation)

          • Eden区:新对象首次分配区域。

          • Survivor区(From/To):存放经过Minor GC存活的对象。

        • 老年代(Old Generation):存放长期存活对象(如多次GC未被回收的对象)。

      • 参数调优

        • -Xms(初始堆大小)、-Xmx(最大堆大小)。

        • 建议:两者设置为相同值以避免动态扩容的性能损耗。

    2. 元空间(Metaspace)(JDK 8+)

      • 取代永久代(PermGen),存储类元数据(类结构、方法、常量池等)。

      • 直接使用本地内存(非堆内存),避免PermGen的OOM问题。

      • 参数调优

        • -XX:MetaspaceSize(初始阈值)、-XX:MaxMetaspaceSize(最大上限)。

  2. 线程私有区域

    1. 虚拟机栈(Java Stack)

      • 每个线程对应一个栈,存储方法调用的栈帧(局部变量、操作数栈等)。

      • 栈深度溢出会抛出StackOverflowError

    2. 本地方法栈(Native Method Stack)

      • 为JVM调用本地方法(Native)服务。

    3. 程序计数器(Program Counter Register)

      • 记录当前线程执行指令的位置(线程切换时恢复执行点)。

二、垃圾回收(GC)机制

  1. 分代回收策略

区域 GC频率 主要算法 典型问题
新生代 复制算法 Eden区快速填满
老年代 标记-清除/整理 Full GC导致应用停顿
元空间 极低 无(直接分配) 类元数据溢出(OOM)
  1. 优化策略

    1. 避免过早晋升:通过-XX:MaxTenuringThreshold控制对象晋升老年代的阈值。

    2. 大对象直接进老年代:通过-XX:PretenureSizeThreshold设置。

三、常见问题与调优实践

  1. OOM(内存溢出)场景

    1. 堆溢出对象过多或内存泄漏(如未释放集合引用)

    2. 元空间溢出:动态生成大量类(如反射、CGLib)。

    3. 栈溢出深度递归或循环调用

  2. 调优工具

    1. jstat:监控堆内存和GC状态。

    2. jmap:生成堆转储快照(分析内存泄漏)。

    3. VisualVM:图形化监控内存、线程、类加载情况。

四、总结

JVM内存模型的核心在于分代设计垃圾回收策略。通过合理设置堆大小、选择GC算法(如G1/ZGC优化低延迟场景)、监控元空间使用,可显著提升应用性能。关键原则是平衡内存分配与回收效率,减少Full GC频率。

  1. JVM参数

-Xss256k -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+UseContainerSupport -XX:MaxRAMPercentage=70.0 -XX:MetaspaceSize=600m -XX:MaxMetaspaceSize=600m -XX:MaxDirectMemorySize=200m -XX:CompressedClassSpaceSize=200m -XX:InitialCodeCacheSize=200m -XX:ReservedCodeCacheSize=200m

这些JVM参数用于配置Java虚拟机的运行时行为和内存管理。以下是每个参数的详细解释:

  1. -Xss256k:设置每个线程的堆栈大小为256KB。默认值通常是1MB或更大,较小的堆栈大小可以减少内存使用,但可能会导致栈溢出错误。

  1. -XX:+UseG1GC:启用G1垃圾收集器(Garbage-First Garbage Collector)。G1GC是一个低暂停时间的垃圾收集器,适用于大多数应用程序。

  1. -XX:MaxGCPauseMillis=100:设置G1垃圾收集器的最大暂停时间目标为100毫秒。G1GC会尝试在这个时间内完成垃圾收集。

  1. -XX:+UseContainerSupport:启用对容器环境的支持,使JVM能够识别和适应容器的资源限制(如CPU和内存)。

  1. -XX:MaxRAMPercentage=70.0:设置JVM可以使用的最大内存为容器或主机可用内存的70%。

  1. -XX:MetaspaceSize=600m:设置元空间(Metaspace)的初始大小为600MB。元空间用于存储类的元数据。

  1. -XX:MaxMetaspaceSize=600m:设置元空间的最大大小为600MB。

  1. -XX:MaxDirectMemorySize=200m:设置直接内存的最大大小为200MB。直接内存用于NIO(非阻塞I/O)操作。

  1. -XX:CompressedClassSpaceSize=200m:设置压缩类空间的大小为200MB。压缩类空间用于存储类指针,以减少内存占用。

  1. -XX:InitialCodeCacheSize=200m:设置代码缓存的初始大小为200MB。代码缓存用于存储JIT(即时编译器)编译的本地代码。

  1. -XX:ReservedCodeCacheSize=200m:设置代码缓存的最大大小为200MB。

这些参数可以根据应用程序的需求进行调整,以优化性能和内存使用。

  1. 垃圾回收


网站公告

今日签到

点亮在社区的每一天
去签到