文章目录
JVM
1、虚拟机组成部分:
- 运行时数据区
- 堆
- 栈、本地方法栈
- 方法区(元空间)
- 程序计数器
- 类装载子系统
- 字节码执行引擎
2、如何查看JVM的系统默认值
第一种: jps 查看正在运行的java程序,然后使用 jinfo -flag 配置项 进程号 查看默认值
eg: jinfo -flag PrintGCDetails 9527
-
Boolean 类型
- -XX: +??? / -XX: -??? +开启,-关闭
- PrintGCDetails
-
KV设置类型
- -XX:属性key=属性值value
- MetaspaceSize
** jinfo -flags pid —>查看所有参数:Non-default VM flags是jvm根据运行环境自动设置的参数,Command line是用户配置的参数
-Xms 等价于-XX:InitialHeapSize 初始堆内存;-Xmx 等价于-XX:MaxHeapSize 最大堆内存,防止频繁GC,建议两者相等。
第二种:
-
java -XX:+PrintFlagsInitial
查看jvm初始化默认配置 -
java -XX:+PrintFlagsFinal
查看jvm被修改过的值
** = 没有更改过的配置, := JVM根据运行环境自动调整过或者认为修改过的配置 -
-XX:+PrintCommandLineFlags 偏重于查看默认垃圾回收器
常用参数:
-Xms: 初始内层大小,默认物理内存1/64,等价于-XX:InitialHeapSize
-Xmx:最大分配内存,默认为物理内存1/4,等价于-XX:MaxHeapSize
-Xss:设置单个线程栈的大小,一般默认为512~1024K,等价于-XX:ThreadStackSize,查出来为0的话,表示使用的是默认值,与平台有关
-Xmn:设置年轻代大小
-XX:MetaspaceSize 设置元空间大小,元空间本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于,元空间并不在虚拟机中,而是使用本地内存。因此默认情况下,元空间的大小仅受本地内存的限制。
-XX:+PrintGCDetails 输出详细的GC收集日志信息
-XX:SurvivorRatio 设置java堆空间 新生代中eden和from 和to空间的比例,默认8:1:1, -XX:SurvivorRatio=8, SurvivorRatio值就是设置eden区的比例占多少,from和to相同
-XX:NewRatio:配置年轻代与老年代在堆结构的占比,默认-XX:NewRatio=2,新生代占1老年代占4,newRatio的值就是老年代与新生代的比
-XX:MaxTenuringThread:设置垃圾的最大年龄,默认值是15。java8中,不能超过15
3、根搜索算法:GCroot 根:
- 相比与引用计数法对循环引用的束手无策,根搜索算法可以很好的解决循环引用的问题
- 是一个集合,集合的元素
- 虚拟机栈中引用的对象,也叫局部变量表
- 方法区中的静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
4、引用类型
- 强引用、软引用、弱引用、虚引用分别是什么?
- 强引用:当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是OOM也不会对该对象进行回收。在java中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。
- 软引用:内存足够不回收,内存不足时被回收。软引用通常用于对内存敏感的程序中,比如高速缓存就用到软引用。
- 弱引用:只要gc,就会被回收
weakHashMap:对应的key是弱引用,gc后,map存储的kv键值对,被回收。 - 虚引用:幽灵引用。虚引用的主要作用是跟踪对象被垃圾回收的状态。
5、GC过程
MinorGC的过程:
1. 首先,当eden区满的时候会触发第一次GC,把还活着的对象拷贝到from区,清空eden区;
2. 当eden区再次触发GC的时候会扫描eden区和from区,对这两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到to区(如果有对象的年龄已经达到了老年的标准,则复制到老年区),然后清空eden和from区,再将from区和to互换表示(谁空谁是to),然后进行下一次GC
5、jvm常用指令
- jsp: 查看java进程;
- jstat: 查看java进程相关信息,包括类加载、编译、内存使用、GC概况;
- jinfo: 查看和调整java进程的运行参数;
- jmap:查看java 进程的内存信息;
- jstack:查看JVM的线程信息。
6、arthas jvm 调优工具
7、GC算法
四大GC算法:
1、引用计数
2、复制拷贝
3、标记清除
4、标记整理
是内存回收的方法论,垃圾收集器就是算法的实现。
8、垃圾收集器
8.1 分类
垃圾收集器种类:Serial、Parallet、CMS、G1
Serial:串行垃圾回收器,它为单线程环境设计而且只使用一个线程进行垃圾回收,会暂停所有的用户线程。不适合服务器环境。
Parallet:并行垃圾回收器, 多个垃圾收集线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景
CMS(concMarkSweep,并发标记清除): 并发垃圾回收器,用户线程和垃圾收集同时执行(不一定并行,可能交替)不需要停顿用户线程,适用于对响应时间有要求的场景。
8.2.7 G1垃圾回收器
G1:是一种服务器端的垃圾收集器,应用在多处理器和大容量内存环境中,在实现高吞吐率的同时,尽可能的满足满足垃圾收集暂停时间的要求。具有以下特点:
1)、能与应用程序线程并发执行
2)、整理空闲空间更快
3)、需要更多的时间来预测GC停顿时间
4)、不希望牺牲更多的时间
5)、不需要更大的Java Heap
G1收集器的设计目标是取代CMS收集器,与CMS相比,在以下方面表现的更出现;
G1是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片;
G1的STW更可控,G1在停顿时间上添加了预测机制,用户可以指定期望停顿时间。
9、JVM调优思路 todo
在理解jvm内存结构以及各种垃圾收集器的前提下,结合具体的业务特点来调整参数,使应用能够正常平稳运行。
10、JVM生命周期
- 虚拟机启动: java虚拟机的启动是通过引导类加载器(bootstrap class Loader)创建一个初始类initial class 来完成的,这个类是由虚拟机的具体实现指定的。
虚拟机的执行: - 一个运行中的虚拟机有着一个清晰的任务:执行java程序。
- 程序开始执行时虚拟机才运行,程序结束虚拟机就停止
- 执行一个所谓的java程序的时候,其实在执行一个叫做java虚拟机的进程。
11、jvm相关错误
- java.lang.StackOverFloeError: 栈溢出,常见的递归调用,结束条件没写好
- java.lang.OutOfMemoryror:java heap space 堆内存溢出
- java.lang.OutOfMemoryror:GC overhead limit exceeded GC回收时间过长,超过98%的时间用来GC,并且回收了不到2%的内存
- java.lang.OutOfMemoryror:Direct buffer memory 频繁分配本地内存,导致本地内存不够用
- java.lang.OutOfMemoryError: Metaspace 元空间溢出
12、JIT
just-in-time, java程序在代码运行的同时编译。比较出名的有方法内联和逃逸分析。
方法内联:在编译时,将方法调用 直接使用 方法体中的代码进行替换;
逃逸分析:如果一个变量的使用,在运行期检测 他的作用范围不会超过一个方法或者一个线程的作用域。那么这个变量就不会被多个线程所共享,也就是说 可以不将其分配在堆空间中,而是将其线程私有化。