目录
一、JVM内存结构
1.3常见OOM错误
Exception in thread “main”: java.lang.OutOfMemoryError: Java heap space
Exception in thread “main”: java.lang.OutOfMemoryError: PermGen space
Exception in thread “main”: java.lang.OutOfMemoryError: <reason> <stack trace>(Native method)
Exception in thread “main”: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
1.4JMM(Java内存模型)
JMM控制java线程间通讯规则,是一个虚拟的概念,他规定了线程之间的共享变量存在主存中,每一个线程都是有一个私有的本地内存来存储主存中的数据副本,每次对主存数据操作都是先复制到本地内存中修改再返回提交给主内存。
1.5类加载器
二、JVM垃圾回收
2.1四种GC算法
2.2GC roots 可达性分析
- 如何判断对象是不是垃圾(可达性分析):
枚举根节点做可达性分析比如上图,对象C就是对象不可达,是垃圾。
- GCroot包括
三、 JVM调优
3.1JVM参数类型
JVM有三种参数类型,标配参数、-X参数、-XX参数
3.2如何查看JVM的一些默认系统值
可以通过以下三种方法罗列:
- -XX:+PrintFlagsinitia:显示所有jvm参数:
- -XX:+PrintflagsFinal :查看修改更新的值
等号前面有冒号代表被修改过的参数:
T是java运行类名,-XX:+PrintflagsFinal 可以运行时修改jvm参数:
- -XX:+PrintCommandLineFlags:可以看见命令行-XX参数,展示的最后一个参数是并行GC回收器
3.3常用JVM基本配置参数
- java8新特性:
- 获取运行时初始内存大小:
这是一个内存16G的电脑设备,可见默认-xms是1/64倍物理内存大小,-xmx是1/4倍物理内存大小
- 常用参数:
四、强软弱虚四大引用
4.1整体架构
Reference强、SoftReference软、WeakReference弱、PhantomReference虚
4.2强引用
- 当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。
- 强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾收集器不会碰这种对象。在 java中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即体该对象以后永远都不会被用到,M也不会回收。因此强引出是造成,ava内存泄漏的主要原因之一。
- 对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 nul,一般认为就是可以被垃圾收集的了(当然具体回收时机还是要看垃圾收集策略)。
- 案例:
程序正常运行,0bj2是强引用,不会被回收,obj1置空所以被回收
4.3软引用
- 软引用是一种相对强引用弱化了一些的引用,需要用java.ang.ref.SoftReference类来实现,可以让对象豁免一些垃圾收集。
- 对于只有软引用的对象来说,当系统内存充足时它不会被回收,当系统内存不足时它会被回收。
- 软引用通常用在对内存敏感的程序中,比如高速缓存就有用到软引用,内存够用的时候就保留,不够用就回收!像mybatis缓存代码一些内部类就是以此实现。
- 案例:
内存够用,所以不会被回收
内存不够用,报错oom:
4.4弱引用
不管内存够不够,一律被回收:
一般软弱引用用于缓存:
4.5WeakHashMap
就是实现了虚引用功能的hashmap,可见GC后hashmap被置空:
4.6虚引用
- 虚引用需要java.lang.ref.PhantomReference类来实现。
- 顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收;它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
- 虚引用的主要作用是跟踪对象被垃圾回收的状态。 仅仅是提供了一种确保对象被 finalize以后,做某些事情的机制。PhantomReference的get方法总是返回null,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入fnalization阶段,可以被gc回收,用来实现比finalization机制更灵活的回收操作。
- 换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理。
- Java 技术允许使用 finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
虚引用案例:把弱引用放在一个队列里:
执行gc后,引用都被回收,但是虚引用会输出引用队列的信息:
虚引用;类似于后置通知:
五、OOM
- java.lang.StackOverflowError
OOM和栈溢出都是错误,最常见的就是方法循环调用
- java.lang.OutOfMemoryError:Java heap space
对象占用堆空间过头:
- java.lang.OutOfMemoryError: GC overhead limit exceeded
GC一直运行:
案例:
全是fullGC,十四万次i:
可见GC每个区回收前后都是一样的,
- java.lang.OutOfMemoryError: Direct buffer memory
一般NIO操作会出现这种OOM:
- java.lang.OutOfMemoryError: unable to create new native thread
高并发场景,不能创建新的本地线程:
- java.lang.OutOfMemoryError: Metaspace
六、垃圾回收器
6.1四种垃圾回收器
- serial串行回收器
在单线程环境中,只有一个gc线程,执行gc时候会暂停用户线程,不适合服务器环境
- parallel并行垃圾回收器
有多个gc线程执行垃圾回收, 用户线程也会暂停,适用于科学计算和大数据处理首台处理等弱交互场景
- CMS并发
用户线程和gc、可以同时执行,适用于强交互场景,但也会有内存碎片问题
- G1回收器
java8诞生,将堆内存分为不同区域,并发进行垃圾回收
6.2生产中怎么配置GC?
- 如何查看默认GC:
-XX:PrintCommandLineFlags -version
- 默认GC有哪些?
- 垃圾收集器在不同分区的使用
6.3七种GC用法:
SerialOld现在已经废弃,一般配完新生代,老年代也会自动配配置对应GC:
参数说明:
Server和Client模式:
6.4G1回收器
- 概念:
配置G1后,不分新生老年代,
从官网的描述中,我们知道G1是一种服务器端的垃圾收集器,应用在多处理器和大容量内存环境中,在实现高吞吐量的同时,尽可能的满足垃圾收集暂停时间的要求。另外,它还具有以下特性:
- 像CMS收集器一样,能与应用程序线程并发执行。
- 整理空闲空间更快。
- 需要更多的时间来预测GC停顿时间。
- 不希望牺牲大量的吞吐性能。
- 不需要更大的Java Heap。
G1收集器的设计目标是取代CMS收集器,它同CMS相比,在以下方面表现的更出色:
G1是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。
G1的Stop The Word(STW)更可控,G1在停顿时间上添加了预测机制,用户可以指定期望停顿时间。
- G1底层原理:
区域化内存划片Region,整体编为了一些列不连续的内存区域,避免了全内存区的GC操作。
核心思想是将整个堆内存区域分成大小相同的子区域(Regjon),在JVM启动时会自动设置这些子区域的大小。
在堆的使用上,G1并不要求对象的存储一定是物理上连续的只要逻辑上连续即可,每个分区也不会固定地为某个代服务,可以按需在年轻代和老年代之间切换。
启动时可以通过参数-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个大小范围在1MB~32MB,最多能设置2048个区域,也即能够支持的最大内存为:32MB*2048=65536MB=64G内存
过程演示:
回收步骤:
- GC如何选型:
6.5GC结合SpringBoot生产部署和调参优化
七、生产环境中的性能监控
7.1常用Linux命令性能评估
- top命令,主要查看PID对应的CPU和内存MEM:
load average系统负载均衡,分别代表一分钟、五分钟、十五分钟的平均负载值,如果三个数的平均值高于60%,一般就认为系统压力过大:
- uptime命令,是top的精简版:
- vmstat:
每两秒采样一次,共采样三次:
- mpstat -P ALL 2:查看所有cpu信息:
- pidstat -u 1 -p:查看每个进程使用cpu的用量分解信息:
- free:查看内存:
- pidstat -p 进程号 -r 采样时间间隔:
- df查看磁盘空间:
- iostat磁盘IO:
- 也可以用pidstat:
- ifstat:网络IO
7.2cpu过高故障排查思路
7.3 github操作-工作中如何高效学习
一般工作中实现一个功能并不是从头开始,站在巨人肩膀上能看的更远,套用优秀框架能帮我们更好的工作和学习,所以要熟练使用GitHub,以下展示了一些常用github操作帮助自己更高效的学习优秀开源框架。
- 基本功能:
- 进阶操作:in关键字组合查询
比如查一个秒杀功能:
- star和fork:
eg:
组合查询:
- awesome命令:
优秀框架,一般用于学习:(redis正常查询会有四万多条记录,但awesome后只有四十多条)
- #L
网页地址后面#L加数字,可以高亮代码提示重要代码,方便程序员之间交流
- github快捷键:
一般常用t快捷键
- 查看大佬:
创建引用的时候可以指定关联的队列,当GC释放对象内存的时候,会将引用加入到引用队列,如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动这相当于是一种通知机制。
学习视频来自尚硅谷,笔记为个人学习总结,新手上路多多包涵~~~
80_GCRoots和四大引用小总结_哔哩哔哩_bilibili