最近在读 Java 程序性能优化,本编主要记录下关于JVM 调优方面的知识点;具体的细节可以去看这本书的第五章。
本章主要讲了:
- JVM 内存模型结构
- 与内存分配相关的 JVM 参数
- 垃圾回收期的种类和使用方法
- 常用的JVM调优参数
JVM 虚拟机内存模型
首先是 JVM(Java 虚拟机) 内存模型,其将内存数据分为 程序计数器、虚拟机栈、本地方法栈、Java 堆和方法区。(注意这里要区分 Java 虚拟机内存模型 和 Java 内存模型(JMM)是不同的,不要混淆)
- 程序计数器(线程私有)
存放下一条运行的指令。 - Java 虚拟机栈(线程私有)
(管理Java函数的调用)和 Java 线程一起创建,保存放的的局部变量、部分结果和方法的调用以及返回。
常遇到的异常:StackOverflowError 和 OutOfMemoryError
在 Hot Spot 虚拟机中,使用 -Xss 参数这只虚拟机栈的大小。
涉及工具:jclasslib - 本地方法栈
管理本地方法的调用
也会抛出 StackOverflowError 和 OutOfMemoryError - Java 堆(线程共享)
几乎所有的对象和数组都是在堆中分配空间。Java 堆分为老年代和新生代两个部分,新生代又细分为eden、survivor space0、survivor space1。
新生代用于存放刚产生的对象,老年代用于存放年龄稍长的对象(经历垃圾回收次数较多的对象)
堆空间基本结构: - 方法区(线程共享)
主要保存类的元数据信息,包含类的类型信息、常量池、域信息和方法信息等。
- 类型信息:类的完整名称、类的修饰符和类的直接接口类表
- 常量池:这个类方法、域等信息所引用的常量信息
- 域信息:域名称、域类型、域修饰符(这个域我没太想明白是哪一部分)
- 方法信息:方法名称、返回类型、方法参数、方法修饰符、方法字节码、操作数栈和方法栈帧的局部变量区大小和异常表。方法区的信息大部分来自 class 文件。在 Hot Spot 虚拟机中,方法区也称永久区,是一块独立于 Java 堆的内存空间。
永久区的 GC: 一是 GC 对永久区常量池的回收;二是永久区对类元数据的回收。
注意: 只要 ClassLoader 被回收,在 Full GC 时,永久区中的类的元数据是完全有可能被回收的。
JVM 内存分配参数
- 设置最大堆内存
最大堆指的是新生代和老年代的大小之和的最大值。-Xmx
- 设置最小堆内存
JVM 启动时,占据的内存大小。
如果 -Xms 指定的数值较小,那么 JVM 为了保证系统为了保证在指定的内存范围内运行,就会更加频繁的尽心 GC 操作,来释放内存空间,增加对 Minor GC 和 Full GC 的次数,对系统性能产生一定的影响。-Xms
- 设置新生代
设置较大的新生代的大小会减小老年代的大小。新生代的大小一般设置为整个堆空间的 1/4 到 1/3
在 Hot Spot 虚拟机中,使用 -XX:NewSize 用于设置新生代的初始大小,设置 -XX:MaxNewSize 用于设置新生代的最大值。-Xmn
注意: 若设置不同的 -XX:NewSize 和 -XX:MaxNewSize 可能会导致内存震荡,产生不必要的系统开销。 - 设置持久代(老年代)
持久代(方法区)不属于堆的一部分。在 Hot Spot 虚拟机中,使用 -XX:MaxPermSize 可以设置持久代的对大值,使用 -XX:PermSize 设置持久代的初始化大小。
持久代的大小直接决定系统可以支持多少个类的定义和多少常量。
一般的应用程序设置为 64M 和 128M 就满足了。 - 设置线程栈
线程栈是线程的一块私有空间(虚拟机栈)。如果栈空间过大,开设线程所需的内存成本就会上升,系统所能支持的线程总数就会下降。
例如设置 -Xss1M,即设置每个线程拥有 1M 的栈空间。-Xss
- 堆的比例分配
新生代:-Xmn、-NewSize、-MaxNewSize
- -XX:SurvivorRatio 是用来设置新生代中,eden 空间和 s0 空间的比例关系。
- -XX:NewRatio 设置新生代和老年代的比例
- -XX:PrintGCDetails 打印堆的实际大小
堆分配参数总结
- -Xms:初始堆大小
- -Xmx:最大堆大小
- -Xss:线程栈的大小
- -XX:MinHeapFreeRatio:设置堆空间的最小空闲比例。当堆空间的空闲内存小于这个数值时,JVM 便会扩大堆内存
- -XX:MaxHeapFreeRatio:设置对空间的最大空闲比例。当对空间的空闲内存大于这个数值时,JVM 便会压缩堆内存
- -XX:NewSize: 新生代大小
- -XX:NewRatio:老年代和新生代的比例
- -XX:SurvivirRatio:新生代中 eden 和 survivor 区的比例
- -XX:PermSize:永久代初始值
- -XX:TargetSurvivorRatio:survivor 区的可使用率。当 survivor 区的空间使用率达到这个数值时,会将对象放入老年代。
视图: