PC寄存器:
- 每个线程有一个PC寄存器
- 在线程创建时创建
- 指向下一条指令的地址
- 执行本地方法时,PC的值为undefined
方法区:
-
保存装载的类信息
- 类型的常量池
- 字段,方法信息
- 方法字节码
JDK6时,String等常量信息在方法区
JDK7时,移动到了堆
和jvm的版本有关系,一般都是保存类的信息,对类的描述
-
通常和永久区(Perm)关联在一起,
Java堆
- 应用系统的对象都保存的堆
- 所有线程共享
- 对分代GC来说,堆也是分代的
java栈:
- 线程私有
- 栈有一系列帧组成
- 帧中保存一个方法的局部变量,操作帧数,常量池指针
- 每一个方法调用创建一个帧,并压栈
栈上分配:
-
小对象(几十个bytes),在没有逃逸的情况下,可以直接分配在栈上
-
直接分配在栈上,可以自动回收,减轻GC压力
-
大对象或者逃逸对象无法在栈上分配
逃逸分析(Escape Analysis)简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。逃逸分析是为了优化 JVM 内存和提升程序性能的。
命令行选项中手动开启逃逸分析(逃逸分析技术在 Java SE 6u23+ 开始支持,并默认设置为启用状态,可以不用额外加这个参数)
逃逸分析的 JVM 参数如下:
- 开启逃逸分析:-XX:+DoEscapeAnalysis
- 关闭逃逸分析:-XX:-DoEscapeAnalysis
- 显示分析结果:-XX:+PrintEscapeAnalysis
保证可见性的方法:
- volatile
- synchronized(unlock之前,写变量值回主存)
- final(一旦初始化完成,其他线程就可见)
volatile:
- 可见性
- 有序性
- 指令重排
-XX:+PrintHeapAtGC 每一次GC后,都打印堆信息
-XX:+TraceClassLoading 监控系统中每一个类的加载(跟踪调试的时候使用)
-XX:+PrintClassHistogram 打印类的使用情况,按下Ctrl+Break后,控制台答应类的信息
堆的分配参数
-Xmx 最大堆
-Xms 最小堆
-Xmn 设置新生代大小(绝对值)
-XX:NewRatio 设置新生代大小(比值)
新生代(Eden+2*s):老年代(不包含永久区)的比值
4 表示 新生代:老年代=1:4,年轻代占堆的1/5
-XX:SurvivorRatio 设置两个Survivor区和eden区的比值
8 表示两个Survivor:eden=2:8,一个Survivor占年轻代的1/10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5qqS7y9v-1614574469688)(C:\Users\wanru\AppData\Roaming\Typora\typora-user-images\1614573778654.png)]
%p 代表java的进程IP
根据实际情况调整新生代和幸存代大小
官方推荐 新生代占堆3/8
幸存代占新生代1/10
在OOM时,记得Dump出堆,确保可以排查现场问题
永久区分配参数
-XX:PermSize 永久区初始空间
-XX:MaxPermSize 永久区最大空间
他们表示,一个系统可以容纳多少个类型,一般几十到几百M
-Xss 栈大小
- 通常只有几百K(栈越小,可跑的线程越多)
- 决定了函数调用的深度
- 每个线程都有独立的栈空间
- 局部变量,参数分配在栈上