JVM内存模型和JVM调优
JVM内存模型
注意:方法区的实现是MetaSpace,JVM中方法区和堆是共享的,每一个线程的自己独立的执行栈,pc计数器,本地方法栈均为线程私有
JVM堆的划分
1、创建的对象都会放入heap中的Eden区
2、当Eden区满时,会开启youngGC,存活对象放入from区
3、下次扫描时,就会扫描Eden区和from区,将存活的对象放入To区,From区和To区进行交换(复制交换)
4、当对象经过15次交换后,将对象放入oldGen(full GC 主要是回收oldGen对象)
GC回收四大算法
1、引用计数
2、复制交换
3、标记-清除
4、标记-清除-压缩
优点:无内存碎片
缺点:三次扫描,耗时大
GC root原理
1、GC root原理
GC root原理:通过对枚举GCroot对象做引用可达性分析,即从GC root对象开始,向下搜索,形成的路径称之为 引用链。如果一个对象到GC roots对象没有任何引用,没有形成引用链,那么该对象等待GC回收。
2、GC root对象是什么?
Java中可以作为GC Roots的对象
1、虚拟机栈(javaStack)(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。
2、方法区中的类静态属性引用的对象。
3、方法区中常量引用的对象。
4、本地方法栈中JNI(Native方法)引用的对象。
JVM参数类型
1、标准参数
- version java -version
- help
2、X参数
- Xint:解释执行
- Xcomp:第一次使用就编译成本地代码
- Xmixed:混合模式
3、XX参数
xx参数分为boolean类型参数 和 kv类型参数
3.1、boolean类型参数参数
-XX:+ 或者 - 某个属性值(+表示开启,-表示关闭)
是否打印GC收集细节
- -XX:-PrintGCDetails
- -XX:+PrintGCDetails
是否使用串行垃圾回收器
- -XX:-UseSerialGC
- -XX:+UserSerialGC
3.2、KV类型参数参数
- -XX:InitialHeapSize=xxxx
- -XX:maxHeapSize=xxx
实例:
查看一个正在运行的java应用,jvm配置如何?
- jps -l 查看正在运行中的java程。
- jinfo -flag PrintGCDetails 进程pid 查看它的某个jvm参数(如PrintGCDetails )是否开启。
- jinfo -flags 进程pid 查看它的所有jvm参数
E:\Intellij IDEA\IDEAProject\test-01>jinfo -flags 3112
Attaching to process ID 3112, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b15
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=132120576 -XX:MaxHeapSize=2097152000 -XX:MaxNewSize=698875904 -XX:MinHeapDeltaBytes=52428
8 -XX:NewSize=44040192 -XX:OldSize=88080384 -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -X
X:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line: -XX:+PrintGCDetails -javaagent:E:\Intellij IDEA\IntelliJ IDEA 2019.1.4\lib\idea_rt.jar=5181:E:\Intellij IDEA\IntelliJ IDEA 2019.1.4\bin -D
file.encoding=UTF-8
-XX:InitialHeapSize=132120576 JVM最初堆内存大小(默认是物理内存的64分之一)
-XX:MaxHeapSize=2097152000 JVM最大堆大小(默认是物理内存的4分之一)
-XX:+PrintGCDetails 打印输出GC回收信息
Heap
PSYoungGen total 37888K, used 4592K [0x00000000d6580000, 0x00000000d8f80000, 0x0000000100000000)
eden space 32768K, 14% used [0x00000000d6580000,0x00000000d69fc330,0x00000000d8580000)
from space 5120K, 0% used [0x00000000d8a80000,0x00000000d8a80000,0x00000000d8f80000)
to space 5120K, 0% used [0x00000000d8580000,0x00000000d8580000,0x00000000d8a80000)
ParOldGen total 86016K, used 0K [0x0000000083000000, 0x0000000088400000, 0x00000000d6580000)
object space 86016K, 0% used [0x0000000083000000,0x0000000083000000,0x0000000088400000)
Metaspace used 3226K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 357K, capacity 388K, committed 512K, reserved 1048576K
JVM查看初始默认值
-XX:+PrintFlagsInitial
使用方式:java -XX:+PrintFlagsInitial 也可以将XX参数配置在VM option中启动引用查看
数据过多,有需要自己查看
uintx MetaspaceSize = 21810376 {pd product}
元空间大小为21M左右
JVM查看修改更新参数值
-XX:+PrintFlagsFinal
使用方式:java -XX:+PrintFlagsFinal 可以将XX参数配置在VM option中启动引用查看
JVM常用参数
-XX:ThreadStackSize 配置线程栈大小
-Xmn:设置年轻代大小 (这是简写形式,我个人喜欢用全称,好记)
-XX:MetaspaceSize 设置元空间大小
元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。