一、Why study jvm
-
无论是Java还是大数据,都会面试JVM相关的信息,无论是性能调优还是参数监控,不管是hadoop系列还是spark系列,它都是跑在JVM之上的,就像hadoop和spark运行,一用就OOM,不同的异常信息采用不同的解决方案,JVM在生产上面是非常非常重要的,最重要的还是GC这块(垃圾收集器),从重要性上来讲,机器上都装jdk的;
-
JVM官网:https://docs.oracle.com/javase/specs/jvms/se8.html/index.html
二、Linux上使用jvm
2.1、Server和Client模式的区别
1、一般32位的Windows操作系统采用的就是Client模式的;64位的操作系统都是Server模式
2、如下在CentOS7上的是Client模式:
[root@sz5i5j-01 ~]# java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
mixed mode:混合型
Java:解释型int、编译型comp
2.2、JVM的三个参数解析
- jinfo -flag PrintGCDetails
- jinfo -flag MetaspaceSize
- jinfo -flag MaxTenuringThreshold
- 学习JVM的终极目标是性能调优,与JVM相关的都是参数控制的,所以首先需要了解的是JVM参数类型:
1)、标准 --> 从jdk1到jdk12都没发生过太大变化,都是比较稳定的,比如:help、classpath
2)、X --> 在各个jdk的版本中可能会发生变化,但是变化较少
3)、XX --> 用的相对较多:
分为两类:a.boolean:定义使用:-XX:[+/-] name
-XX:+UseG1GC -XX:-UseGIGC
jps --> pid
jinfo -flag name pid
b.非boolean:-xx:name=value
面试题jdk7 --> jdk8发生的变化?
jdk7:永久代
jdk8: Metaspace
1、解释型:
[root@sz5i5j-01 ~]# java -Xint -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, interpreted mode)
2、编译型:
[root@sz5i5j-01 ~]# java -Xcomp -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, compiled mode)
在IDEA中尝试运行:
1、写一个输出程序,sleep让这个程序睡一会:
package com.ruozedata.hadoop.jvm;
public class JvmDemo {
public static void main(String[] args) {
System.out.println("jvm");
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在windows本地运行cmd,输入jps -l,查看详细正在运行的程序:
1、查看运行的进程:
C:\Users\Administrator>jps -l
10564 com.ruozedata.hadoop.jvm.JvmDemo
10264 org.jetbrains.jps.cmdline.Launcher
12712
16712 org.jetbrains.jps.cmdline.Launcher
18488
19596 sun.tools.jps.Jps
2、-表示没有开启:
C:\Users\Administrator>jinfo -flag PrintGCDetails 10564
-XX:-PrintGCDetails
3、需要在下图中Edit Configurations进行编辑才okay
C:\Users\Administrator>jps -l
7760 com.ruozedata.hadoop.jvm.JvmDemo
3828 sun.tools.jps.Jps
10264 org.jetbrains.jps.cmdline.Launcher
12712
1656 org.jetbrains.jps.cmdline.Launcher
18488
4、再次验证:+表示开启
C:\Users\Administrator>jinfo -flag PrintGCDetails 7760
-XX:+PrintGCDetails
- jdk8并没有采用G1GC作为我们的垃圾回收器
布尔类型小结:
1、通过jps -l获取pid
2、jinfo -flag name pid
非布尔类型:
1、MetaSpaceSize的大小:
C:\Users\Administrator>jinfo -flag MetaspaceSize 8852
-XX:MetaspaceSize=21807104
2、修改Metaspace空间的大小:
还是去到Edit Configuration中去修改,以空格为间隔进行参数修改:
-XX:+PrintGCDetails -XX:MetaspaceSize=128m
3、修改后重新查看大小:
C:\Users\Administrator>jinfo -flag MetaspaceSize 21260
-XX:MetaspaceSize=134217728
1、年龄阈值,默认15(对象被复制的次数)
C:\Users\Administrator>jinfo -flag MaxTenuringThreshold 21260
-XX:MaxTenuringThreshold=15
2.3、Jinfo命令的详细使用
Jinfo的用法:
C:\Users\Administrator>jinfo
Usage:
jinfo [option] <pid>
(to connect to running process)
jinfo [option] <executable <core>
(to connect to a core file)
jinfo [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both of the above
-h | -help to print this help message
-
1、初始堆栈内存大小:
C:\Users\Administrator>jinfo -flag InitialHeapSize 16404 -XX:InitialHeapSize=268435456
-
2、最大堆栈内存:
C:\Users\Administrator>jinfo -flag MaxHeapSize 16404 -XX:MaxHeapSize=4267704320
-
3、进程运行的详细信息:
在Command line中显示的参数就是我们在IDEA项目中配置的Edit Configuration中配置的;C:\Users\Administrator>jinfo -flags 16404 Attaching to process ID 16404, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.161-b12 Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4267704320 -XX:MaxNewSize=1422393344 -XX:MetaspaceSize=134217728 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC Command line: -XX:+PrintGCDetails -XX:MetaspaceSize=128m -javaagent:D:\intellij idea\IntelliJ IDEA 2018.1\lib\idea_rt.jar=53393:D:\intellij idea\IntelliJ IDEA 2018.1\bin -Dfile.encoding=UTF-8
小结:
jinfo -flag name pid
jinfo -flags pid
2.4、PrintFlags参数系列
-XX: +PrintFlagsInitial (最初始化的参数值)
-XX: -PrintFlagsFinal (可能被改过的参数值)
在Linux上把相关参数写到一个文件中去,然后grep过滤出文件中的参数:
1、把参数写到a.log中去
[root@hadoop002 ~]# java -XX:+PrintFlagsInitial > a.log
[root@hadoop002 ~]# ll
total 72
-rw-r--r-- 1 root root 72430 May 15 12:45 a.log
2、找出参数
[root@hadoop002 ~]# cat a.log|grep InitialHeapSize
uintx InitialHeapSize = 0 {product}
3、符号表示的含义:
= 默认值
:= 修改过的
2.5、-Xmx和-Xms参数
问题:如上两个参数-Xmx和-Xms属于哪一类参数?
- 答:属于XX参数,
-Xms:–> min --> -XX:InitialHeapSize ( jvm堆的最小值)
-Xmx:max --> -XX:MaxHeapSize(JVM堆的最大值)
-Xss:全称:-XX:ThreadStackSize
这两个参数在一般情况下设置的是一样的,查看最大的Heap和最小的Heap大小
最大堆栈内存是4070m,最大堆栈内存是总内存的1/4;
C:\Users\Administrator>jinfo -flag MaxHeapSize 15104
-XX:MaxHeapSize=4267704320
初始化堆栈是256m,机器内存是16G,初始化堆栈内存一般是总内存的1/64;
C:\Users\Administrator>jinfo -flag InitialHeapSize 15104
-XX:InitialHeapSize=268435456
修改MaxHeapSize和InitialHeapSize的大小?
在IDEA的项目中直接修改参数:
-
添加-Xmx10m -Xms10m
-
去到cmd黑窗口中进行验证:修改完后最大和最小的两个堆内存大小是一样的
1、最大堆栈就是10m
C:\Users\Administrator>jinfo -flag MaxHeapSize 18224
-XX:MaxHeapSize=10485760
2、初始堆栈也是10m
C:\Users\Administrator>jinfo -flag InitialHeapSize 18224
-XX:InitialHeapSize=10485760
3、查看这个进程的详细信息:
C:\Users\Administrator>jinfo -flags 18224
Attaching to process ID 18224, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=10485760 -XX:MaxHeapSize=10485760 -XX:MaxNewSize=3145728 -XX:MetaspaceSize=134217728 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=3145728 -XX:OldSize=7340032 -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line: -XX:+PrintGCDetails -XX:MetaspaceSize=128m -Xmx10m -Xms10m -javaagent:D:\intellij idea\IntelliJ IDEA 2018.1\lib\idea_rt.jar=57657:D:\intellij idea\IntelliJ IDEA 2018.1\bin -Dfile.encoding=UTF-8
3、ThreadStackSize运行后值是0,为什么?
C:\Users\Administrator>jinfo -flag ThreadStackSize 18224
-XX:ThreadStackSize=0
2.6、JVM运行时的数据区
- https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5
Java运行时的数据区:是一个规范,内存结构是一个实现
The pc Register
Java Virtual Machine Stacks
Native Method Stack
运行池中包含方法区,有堆Heap,有虚拟机栈(VM Stack),本地方法栈,PC计数器;
做GC时的重点,方法区域和堆;Heap是共享的,is shared among all Java Virtual Machine Threads.
装的是对象实例和数组,会被自动的存储管理系统(GC来进行管理)
Class User{
id name
}
User user = new User()
等号左边的叫引用,右边的叫对象,对象是存储在Heap中的;JVM虚拟机是有一个方法区的,它存储的class信息的,包括常量池和实例对象;方法区在1.8中就是MetaSpace,在堆中能存东西,在MetaSpace中也能存信息。
引用(栈),对象(Heap)中,User.class(metaspace中);
2.7、JVM的内存模型
在jdk1.8中,主要分为两个区域,堆(heap)和非堆(MetaSpace),在堆中,s0和s1的大小是一样的,同一时间点只有一个是能用的,大多数场景中new出来的东西首先分配到eden区,如果eden区满了,进行垃圾回收,对象是活的,就到s1区去,每一次倒腾的过程都有1个年龄+1,年龄到了15的时候就进入了老龄代
- CCS是什么呢,CompressedClassPointers压缩类指针,如果开启了CCS意识就是使用了短指针(32位),如果没有开启短指针,这个部分就是不存在的
GC垃圾回收器的关键所在: