Skip to content

JVM 内存分配机制

JVM 内存分配机制

JVM 内存介绍

JVM 是一种用于计算机设备的规范,他是一个虚构出来的计算机,是通过在实际的计算机仿真模拟各种计算机功能来实现的。

Java 语言的一个非常重要的特点就是与平台的无关性,而使用 java 虚拟机是实现这一特点的关键。一般语言要在不通的平台上运行,至少需要编译成不同的目标代码,而引入 java 语言虚拟机后,java 语言在不通平台上运行时不需要重新编译,java 语言使用 java 虚拟机屏蔽了与具体平台相关的信息,使得 java 语言编译程序的时候只需生成在 java 虚拟机上运行的目标代码,就可以在多重平台上不加修改的运行。Java 虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是 Java 能够“一次编译,多出运行”的原因。

JVM 内存介绍

JVM 内存介绍

JVM 参数配置性能场景

  1. 寻求当前硬件配置下的最佳参数配置
  2. 设置线程限制,吞吐量上不去,系统资源使用率不高
  3. JVM 配置问题,响应时间长,Java 应用 FULLGC 频繁

启动 Java springBoot 应用

java -jar miss-tools.jar --server.port=8081 --server.tomcat.threads.max=10 --server.tomcat.threads.min-spare=50 -Xms512m -Xmx512m -Xmn128m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC

JVM 参数

  • -Xmx3550m:设置 JVM 最大堆内存为 3550M。
  • -Xms3550m:设置 JVM 初始堆内存为 3550M。此值可以设置与-Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存
  • Xss128k:设置每个线程的栈大小
  • -Xmn2g:设置年轻代大小为 2G,此值关系到 JVM 垃圾回收,对系统性能影响较大,官方推荐配置为整个堆大小的 3/8
  • -XX:NewSize=1024m:设置年轻代初始值为 1024M。
  • -XX:MaxNewSize=1024m:设置年轻代最大值为 1024M。
  • -XX:PermSize=256m:设置持久代初始值为 256M。
  • -XX:MaxPermSize=256m:设置持久代最大值为 256M。
  • -XX:NewRatio=4:设置年轻代与年老代的比值,表示年轻代比年老代为 1:4
  • -XX:SurvivorRatio=4:设置年轻代中 Eden 区与 Survivor 区的比值。表示 2 个 Survivor 区与 1 个 Eden 区的比值为 2:4
  • -XX:MaxTenuringThreshold=7:表示一个对象如果在 Survivor 区(救助空间)移动了 7 次还没有被垃圾回收就进入年老代。如果设置为 0 的话,则年轻代对象不经过 Survivor 区,直接进入年老代,对于需要大量常驻内存的应用,这样做可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在 Survivor 区进行多次复制,这样可以增加对象在年轻代存活时间,增加对象在年轻代被垃圾回收的概率,减少 Full GC 的频率,这样做可以在某种程度上提高服务稳定性

GC 回收集器配置

串行收集器器
  • -XX:+UseSerialGC:设置串行收集器
并行收集器(吞吐量优先)
  • -XX:+UseParallelGC:设置年轻代为并行收集器
  • -XX:ParallelGCThreads=20:配置并行收集器的线程数,建议配置与 CPU 数目相等
  • -XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0 开始支持对年老代并行收集
  • -XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间(单位毫秒)。如果无法满足此时间,JVM 会自动调整年轻代大小,以满足此时间。
  • -XX:+UseAdaptiveSizePolicy:并行收集器会自动调整年轻代 Eden 区大小和 Survivor 区大小的比例,以满足设定的最长垃圾回收时长。
并发收集器(响应时间优先)
  • -XX:+UseConcMarkSweepGC:即 CMS 收集,设置年老代为并发收集。CMS 收集是 JDK1.4 后期版本开始引入的新 GC 算法。它的主要适合场景是对响应时间的重要性需求大于对吞吐量的需求,能够承受垃圾回收线程和应用线程共享 CPU 资源,并且应用中存在比较多的长生命周期对象。CMS 收集的目标是尽量减少应用的暂停时间,减少 Full GC 发生的几率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代内存。
  • -XX:+UseParNewGC:设置年轻代为并发收集。可与 CMS 收集同时使用
  • -XX:CMSFullGCsBeforeCompaction=0:并发收集器不对内存空间进行压缩和整理,内存使用效率降低。此参数设置运行 0 次 Full GC 后对内存空间进行压缩和整理,即每次 Full GC 后立刻开始压缩和整理内存。
  • -XX:+UseCMSCompactAtFullCollection:打开内存空间的压缩和整理
  • -XX:CMSInitiatingOccupancyFraction=70:表示年老代内存空间使用到 70%时就开始执行 CMS 收集,以确保年老代有足够的空间接纳来自年轻代的对象,避免 Full GC 的发生。

java 自带性能分析工具

  • jconsloe:

JConsole 是一个基于 JMX(Java Management Extensions)的可视化监控工具,它可以监控 JVM 的各项指标,如内存使用情况、线程数、类加载情况等。通过 JConsole,我们可以实时查看 JVM 的运行状态,对垃圾回收、线程等方面进行优化。 使用方法:在命令行中输入 jconsole 命令启动 JConsole,然后选择需要监控的进程即可。

java -Dcom.sun.management.jmxremote.port=8079 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=${ip} -jar demo.jar

VisualVM

VisualVM 是一个免费的的 Java 代码分析工具,是 Java SE 的一部分,可以帮助我们准确地测量程序的性能指标,如 CPU 和内存使用情况、线程和垃圾回收等。同时,VisualVM 还提供了强大的插件系统,可以扩展其功能,以应对不同的需求。

  • 使用方法:在命令行中输入 jvisualvm 命令启动 VisualVM,然后选择需要监控的进程即可。

jps

jstat

jstat 是一个监控 JVM GC 情况的实用工具,可以帮助我们获取 JVM 的各种统计信息,如堆内存使用情况、GC 执行次数和执行时间等。通过对 jstat 输出的数据进行分析,我们可以了解 JVM 的 GC 行为,找出内存泄漏和其他性能问题等。

  • 使用方法:在命令行中输入 jstat 命令,然后指定相应的选项即可获取监控数据。 jstat -gc pid 2s 10

jmp

jmap 是一个 Java 堆分析工具,可以用于生成 JVM 堆转储文件以及获取 JVM 的内存映像文件。通过对 jmap 输出的数据进行分析,我们可以诊断程序的内存问题,如内存泄漏、对象创建过多等。

  • jmap -heap pid
  • jmap pid
  • 使用方法:在命令行中输入 jmap 命令,然后指定相应的选项即可生成相应的文件。

jstack

JPS 和 JSTACK 是 Java 自带的命令行工具,可以用于监控和调试 Java 程序。JPS 可以列出当前所有正在运行的 Java 程序的进程 ID 和类名,而 JSTACK 可以获取指定进程的线程栈信息,帮助我们分析程序的性能问题。 jstack -l pid >1.txt

  • 使用方法:在命令行中输入 jps 和 jstack 命令,然后指定相应的选项即可