无知的我正在复盘JVM。。。
笔记特点是
- 重新整理了涉及资料的一些语言描述、排版而使用了自己更容易理解的描述。。
- 提升了总结归纳性
- 同样是回答了一些常见关键问题。。
文章目录
JVM-是什么
JVM在总体上的分类
- JVM规范 打开Oracle官网文档可以查看
- JVM实现 最常用的是Oracle公司使用的Hotspot虚拟机
JVM与JDK的区别
- JRE = JVM +Java标准库
- JDK = JRE + 开发调试诊断工具
JVM-跨平台跨语言
跨平台
借助JVM,类可以在多个操作系统上运行 且 效果一致。
跨语言
JVM只识别Class文件,与语言是解耦的。比如说Groovy、kotlin、Scala等语言都是编译成字节码,JVM都可以识别他们,从而在JVM上运行。//一定程度上奠定了Java语言强大的生态圈
JVM-运行时数据区
JVM-堆空间
堆内存分为
新生代和老年代
其中新生代又分为Eden(80%)、S0、S1
堆空间运行机制
新生代采用复制算法;老年代采用其他算法
为什么新生代又要划分
这是为了提高空间利用率,解决原本空间利用率只有50%的问题
当新创建对象时,其会被放在Eden
当Eden满了时,发生第一次垃圾回收、将对象复制到S0
当发生下一次垃圾回收时,如果Eden又满了,复制到S1,同时把上一次在S0的也复制S1
- 如果S1满了、且垃圾回收发生了15次以上,复制到到老年代
//结果是 每次仅仅浪费10%的空间
//为什么能这样做? 这是因为对象很快就会变成垃圾,那么Eden可以划分很大的空间
JVM-内存溢出示例
JVM-内存泄露
是什么
当无用的对象继续占用内存时,这些不使用的内存,没有被释放
典型场景是 当每一个请求或者每一次操作处理时,都为其分配了内存,却有一部分不能回收,随着处理的请求越来越来多,内存泄露就越来越严重。
与内存溢出的关系
不被处理的内存泄露会随着时间推移造成内存溢出
内存溢出是 资源管理、程序BUG导致的
内存泄露是 内存不足和内存溢出导致的
JVM-对象头
是什么
- 类型指针是 对象指向自身元类型的指针。//作用是 虚拟机通过这个指针,确定这个对象是哪个类的实例
分析对象内存的占用
JVM-常用JVM启动参数
JVM-设置堆空间的最大值要考虑的
推荐配置系统或容器的可用内存的 70%~80%最好。
之后,还要考虑到系统自己的内存、其他空间的内存来调整
JVM-排查OOM的手段
查看控制台异常信息
VisualVM查看导出异常文件
这需要设置“VM options”参数。可查看原因、异常位置
//机制是,当该异常出现时,会自动导出异常文件到项目的根目录下
//ViusalVM在安装了hotsopt的JDK(比如JDK1.8)中的根目录
JVM-Java8中默认使用的垃圾收集器
Java8的Hostpot JVM 使用的是并行垃圾收集器(Parallel GC),其包含两个收集器:一是Parallel Scavenge;一是Parallel Old。
其他厂商提供的JDK8也基本上默认使用该垃圾收集器
JVM-并行垃圾收集
是什么
使用多个GC worker 线程并行地执行垃圾收集
好处是
能够充分利用多核CPU的能力,缩短垃圾收集的暂停时间
在应用场景中
除了单线程的GC外,PS、CMS、G1等新型垃圾收集器都是用多线程并行执行CPU操作
- 当CPU使用的是用户线程、发生垃圾回收时,程序进入安全点而暂停所有用户线程,开启GC线程并行地进行垃圾回收
JVM-安全点
安全点-是什么
JVM在字节码指令中选择的一些不会发生引用变化的指令。//比如方法调用、循环跳转、异常跳转等
安全点-为什么
为了确保用户暂停的这行字节码不会发生引用关系变化
安全点-机制
GC要暂停业务线程,就要主动式中断,而不是抢断
主动式中断是 设置一个中断标志,各个业务线程在运行过程中不断地主动轮询这个标志
- 如果发现中断标志为true,就会在自己最近的“安全点”上主动挂起
安全区域-是什么
引用关系不会发生变化的某一段代码
安全区域-为什么
这是因为当业务线程处于sleep()、Blocked状态时,那么程序没有办法进入安全点
JVM-排查CPU突然飙升
- TOP命令 找到消耗很高的CPU进程的ID(假设2732)
- TOP -P 2732 单独监控该进程
- 在第二步的监控界面输入H 获取当前进程的所有线程信息
- 找到消耗CPU特别高的线程编号PID
- 执行JSTACK 2732
- …
JVM-类加载
@加载Loading阶段详解
- 转换Class为二进制字节流——通过这个类的全限定名
- 转换这个字节流所代表的静态存储区(字符串常量池、方法等等) 为 方法区的运行时数据结构
- 生成一个代表这个类的java.lang.Class对象——在内存中。//这个对象作为方法区中这个类的各种数据的访问入口
类加载器是什么
通过这个类的全限定名,来获取该类的二进制字节流的动作
//结果是 让程序自己决定“如何获取所需的类”
JVM-G1收集器的特点
是什么
垃圾优先。就是哪一块垃圾最多,就优先处理它
处理方式
- 空间整合
- 多线程+并发+可预测停顿