1、什么是JVM?
1)机器码翻译(翻译.class文件到机器指令的一个转换)
2)内存管理(因为JVM提供了内存管理功能,让开发人员只需要去关注代码逻辑开发就可以。)
Java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行,Java虚拟机中的Java解释器负责将字节码文件解释成为特定的机器码进行运行。因此在运行时,Java源程序需要通过编译器编译成为.class文件。
2、为什么要学习JVM?
是因为程序出现内存溢出、内存泄漏的问题时候,我们是一无所知的,我们的内存管理已经交给JVM了,所以我们要学习JVM
3、运行时数据区
程序计数器:指向当前线程正在执行的字节码指令的地址、行号
虚拟机栈:存储当前线程运行方法所需要的数据、指令、返回地址
本地方法栈:带native修饰的方法就是本地方法,没有实现类(c、c++实现)
存储当前线程运行本地方法所需要的数据、指令、返回地址
方法区:类信息(类的原信息)、常量(1.7)、静态变量、JIT(运行时动态生产的代码class)
Heap堆:存放的是对象、数组等
JMM:内存模型:
新生代采用复制回收算法:
系统中对象的生命周期不一样,所以heap内存才会进行分代存储
新生代为什么分为3块,并且比例为8:1:1?
98%的对象在新生代区进行young Gc(minor Gc)的时候会被回收掉,不能回收掉的放在s1里面
新生代和老年代的默认比例是1:2
什么样的对象需要呗GC?
JVM对象分配?
1、通过cas机制去开辟空间,保证所有线程开辟空间同步执行(指针碰撞,内存规整)
2、free list 空闲列表
栈上分配:TLAB: thread local ALLACTION BUFFER 栈上分配,jvm为每一个线程在eden单独开辟一个空间,存储对象
可以通过-XX:+UseTLAB 来设置大小
Meta Space区域:属于对外内存,可以无限扩容,需要定义大小,不是越大越好
堆:
-Xms20M starting 堆的起始大小
-Xmx max 堆的最大大小
-Xmn new 堆的新生代大小
对象分配eden,指定新生代eden、s0、s1分配比例
-XX:SurvivorRatio=8
8:1:1
对象很大
-XX:PretenureSizeThreshold=3145728 3M
长期存活的对象,age
-XX:MaxTenuringThreshold=15
动态对象年龄判定
相同年龄所有对象的大小总和 > Survivor空间的一半
分配担保
Minor GC 之前检查老年代最大可用连续空间是否>新生代所有对象总空间
Minor GC 新生代eden区
Major GC 老年代old区
Full GC minor Gc + Major Gc
什么样的对象需要回收?
回收
方法论
标记-清除算法:出现的比较早,效率不高,需要去标记,空间碎片,不是连续空间
复制-回收算法:实现简单、高效,直接复制,复制后是连续的,缺点是浪费空间
标记-整理算法:连续空间,没有碎片,效率不高
单线程和多线程快?
8核多线程快
垃圾收集器
STW Stop The World
Serial(新生代):单线程回收
ParNew (新生代):多线程回收,充分的资源利用率
-XX:ParallelGCThreads 控制回收多线程的个数
Parallel Scavenge (全局)(新生代)
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)
-XX:MaxGCPauseMillis=n GC停顿时间
-XX:GCTimeRatio=n GC时间
-XX:UseAdaptiveSizePolicy GC Ergonomics 减少垃圾收集时间
Serial Old(老年代)
CMS备用预案 Concurrent Mode Failusre时使用
标记-整理算法
Parallel Old(老年代)
标记-整理算法
CMS(老年代)
标记-清除算法
减少回收停顿时间
碎片: -XX:CMSInitiationgOccupancyFraction
Concurrent Mode Failure 启用Serial Old
-XX:+UseCMSCompactAtFullCollection Full GC的时候,要不要开启压缩
-XX:CMSFullGCsBeforeCompaction 执行多少次不压缩FullGC后 来一次带压缩的 0 表示每次都压
-XX:+UseConcMarkSweep 设置CMS算法
G1:分块,复制回收、标记清楚算法,会选择垃圾最多的区块进行优先回收
回收的时间节点?
安全点?
安全点:执行比较久的过程之前或者之后,来做一个停顿,这个点就是安全点
方法调用之前或者之后、循环跳转、方法跳转、异常跳转
1、抢占式:当Gc线程需要执行的时候,应用线程会检查自己是否在安全点上,如果再就stop the world
2、主动式中断:如果垃圾回收器进行回收操作的时候,会设置一个标识,应用线程执行的时候,去检查标识,如果标识存在就停止,等待标识去除后,再进行应用的调用
安全区域?
就是GC线程执行的过程,如果线程在安全区域,则线程可以继续执行
如何查看当前使用的是什么垃圾回收器?
-XX:+PrintFlagsFinal 将垃圾收集器打印到启动日志中
-XX:+PrintCommandLineFlags
server client
MBean
GC日志
1.输出日志
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-Xloggc:/home/administrator/james/gc.log
-XX:+PrintHeapAtGC
2.日志文件控制
-XX:-UseGCLogFileRotation
-XX:GCLogFileSize=8K
3.怎么看
JDK自带的 监控工具
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/toc.html
jmap -heap pid 堆使用情况
jstat -gcutil pid 1000 GC数据统计
jstat -gccause pid 1000 GC引起的原因
jstack 查看线程dump
jvisualvm
jconsole
MAT
http://help.eclipse.org/oxygen/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/administrator/james/error.hprof
怀疑:
1.看GC日志 126719K->126719K(126720K)
2.dump
3.MAT
1.占用Retained Heap
2.看有没有GC Root指向
VM参数
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
什么条件触发STW的Full GC呢?
Perm空间不足;
CMS GC时出现promotion failed和concurrent mode failure(concurrent mode failure发生的原因一般是CMS正在进行,但是由于老年代空间不足,需要尽快回收老年代里面的不再被使用的对象,这时停止所有的线程,同时终止CMS,直接进行Serial Old GC);
(promontion faild产生的原因是EDEN空间不足的情况下将EDEN与From survivor中的存活对象存入To survivor区时,To survivor区的空间不足,再次晋升到old gen区,而old gen区内存也不够的情况下产生了promontion faild从而导致full gc )
统计得到的Young GC晋升到老年代的平均大小大于老年代的剩余空间;
主动触发Full GC(执行jmap -histo:live [pid])来避免碎片问题。
java
-Xms8m -Xmx64m -verbose:gc
-Xloggc:/home/administrator/james/gc.log
-XX:+PrintHeapAtGC
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCTimeStamps
-XX:+PrintCommandLineFlags
-XX:+PrintFlagsFinal
-XX:+PrintGCDetails
-XX:+UseConcMarkSweepGC
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=9004
-Djava.rmi.server.hostname=177.1.1.122
-jar jvm-demo1-0.0.1-SNAPSHOT.jar > catalina.out 2>&1 &
java -Xms128m -Xmx128m -verbose:gc -Xloggc:/home/administrator/james/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/administrator/james/error.hprof -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCTimeStamps -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=9004 -Djava.rmi.server.hostname=177.1.1.122 -jar jvm-demo1-0.0.1-SNAPSHOT.jar > catalina.out 2>&1 &
java -Xms128m -Xmx128m -verbose:gc -Xloggc:/home/administrator/james/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintHeapAtGC -XX:HeapDumpPath=/home/administrator/james/error.hprof -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCTimeStamps -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:+PrintGCDetails -XX:+UseCMSCompactAtFullCollection -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=9004 -Djava.rmi.server.hostname=177.1.1.122 -jar jvm-demo1-0.0.1-SNAPSHOT.jar > catalina.out 2>&1 &
-XX:+CMSScavengeBeforeRemark
死锁对系统的影响?系统资源是有限的,浪费系统资源