JVM内存模型
# JVM内存模型

JVM虚拟机主要包含 类装载子系统、字节码执行引擎、运行时数据区
# 类装载子系统
实现类的加载过程 C++实现
# 字节码执行引擎
- 实现代码的执行 C++
- 变更程序计数器,记录当前程序的执行位置,GC后通过该标识来定位需要执行的代码位置。
# 运行时数据区
# 堆
大部分new 的对象都是在堆中开辟空间。部分会在栈中开辟空间。
栈中开辟空间需要开启逃逸分析 和 标量替换。JDK1.7之后默认开启(详细信息查看:JVM对象创建与内存分配机制 (opens new window))
# 栈
局部变量表存储局部变量
操作数栈 对 局部变量 进行 出栈入栈操作
动态连接 实现 符号引用转换为直接引用
方法出口 记录 方法执行完成后 返回上一个方法的位置,执行调用方的后续代码。
栈中的每个方法会产生一个栈帧,每个栈帧都有一个完整的结构。栈帧空间在方法的执行而产生,在方法的结束而销毁。
# 本地方法栈
在Java初期,由于很多库都是由C/C++实现,为了能够调用这些方法才有了本地方法栈的功能
由native修饰的方法
# 方法区(元空间)
符号信息(类信息、静态变量、常量)
JDK1.8使用的是直接内存,即扣除堆、栈外剩余的内存。
如果启动时未设置值,默认为21M,如果超过21M则会发生FullGC ,所以建议设置默认值(8G建议256M),会根据GC后剩余的大小自动伸缩。
# 程序计数器
记录程序正在运行或者马上运行的位置(内存指针位置)。
由字节码执行引擎进行更改。C++
# 一、JVM内存参数

示例:
java ‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐jar test.jar
-Xss:每个线程栈大小 -Xss设置越小,说明一个线程栈里能分配的栈帧就越少,但是对JVM整体来说能开启的线程数会更多
-Xms:初始堆大小,默认物理内存的1/64
-Xmx:最大堆大小,默认物理内存的1/4
-Xmn:新生代大小
-XX:NewSize:设置新生代初始大小
-XX:NewRatio:默认2表示新生代占年老代的1/2,占整个堆内存的1/3
-XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存
-XX:MaxMetaspaceSize :设置元空间最大值,默认值 -1即不限制,只受限于本地内存大小,元空间无固定初始大小
-XX:MetaspaceSize : 指定元空间(方法区)触发FullGC的初始阈值,以字节为单位,默认是21M,达到该值会触发Full GC进行类型卸载,同事收集器会对该值进行调整:如果释放了大量空间,就适当降低该;如果释放了少量空间,在不超过-XX:MaxMetaspaceSize(如果设置了元空间最大值)的情况下,适当提高该值,这个跟早期jdk版本的-XX:PermSize参数意思不一样,-XX:PermSize代表永久代的初始容量。
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
提示
# 由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动时发生大量Full GC,一般是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样,并设置的比触发Fullgc阈值初始值(21M)要大,对于8G的物理机,一般建议设置256M
注意
# 结论:尽可能让对象都在新生代里分配和回收,尽量别让太多的对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收
# 二、Minor GC ,Full GC 触发条件
Minor GC触发条件:
当Eden区满时,触发Minor GC。
Full GC触发条件:
- 调用System.gc时,系统建议执行Full GC,但是不必然执行
- 老年代空间不足(达到75%或者设定值)
- 方法区空间不足
- 通过Minor GC后进入老年代的平均大小大于老年代的可用内存(对象动态年龄判断)
- 由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
- 空间担保机制触发(详细信息查看:JVM对象创建与内存分配机制 (opens new window))
上次更新: 2026/3/11 22:17:56