本文最后更新于363 天前,其中的信息可能已经过时,如有错误请发送邮件到3368129372@qq.com
硬件->操作系统->jvm
执行流程
- java代码转字节码
- 字节码加载到内存
- 字节码翻译成底层操作系统指令
- native实现(c或者c++)
组成
-
程序计数器
- 线程私有的,每个线程一份,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。
-
JVM堆
-
JVM栈
区别:栈一般存储局部变量,方法调用;堆一般存储Java对象和数组
栈内存是线程私有的;堆内存是公有的
栈报错:StackOverFlowError
堆报错:OutOfMemoryError -
直接内存
- 不由JVM直接管理,为系统内存,分配成本高,读写性能高。
- 用于NIO操作,一般的IO操作需要把系统内存复制带jvm的内存中,耗时就会长很多,直接内存两边都可以访问。
-
类加载器
- 将字节码文件加载到JVM中使其能运行起来
垃圾回收
-
何时可被回收?
- 无人引用
如何定位垃圾? - 引用计数法
- 可达性分析算法(不能沿着GC Root找到相应的对象)
- 无人引用
-
垃圾回收算法
- 标记清除算法:找到存活的,其他全清掉(碎片化严重,存数组之类的会出现问题)。
- 标记整理算法:清除了之后把内存整理到一起,但性能会低
- 复制算法,把清楚后的内存复制到另一块大小相同的内存之中
-
分代回收
- 新生代占1/3,老年代占2/3
- 新生代中,Eden、from与to区占8:1:1
- 流程:
伊甸园区满了之后,挑选存活的复制到to区,清空前两个
下一次满的时候把Eden与to里面的复制到from中,在下一次放到to中……
移动太多次(或者内存不足)之后就会把最开始的那个移动到老年代中
-
名词解释
-
辣鸡收集器
- 串行辣鸡收集器:
单线程执行垃圾回收,所有线程STW(stop-the-world) - 并行辣鸡收集器(java8默认)
多线程执行垃圾回收,所有线程STW(stop-the-world) - CMS并发辣鸡收集器
- 并发,标记-清除算法,针对老年代。垃圾回收时能正常运行。
- 先探索跟GC Root相邻的节点,由于其他线程能同时进行,在运行时原本的垃圾可能不能被回收了,需要再重新标记一下(双检测)。
- 初始标记阻塞,后续标记以及清理都是并发的
- G1辣鸡收集器
- jdk9之后默认用的,划分了多个区域。
- 作用于新生代与老年代。
- 分为三个阶段:新生代回收、并发标记、混合收集
- (并发失败)回收速度赶不上创建新对象的速度,会触发Full GC
- 新生代占比5%-6%888
- 年轻代垃圾回收:复制算法,多个伊甸园区满了之后就会垃圾回收复制到S区,这个跟之前的算法差不多(存在STW)
- 并发标记:老年代超过45%就会进行并发标记,此时不会STW,在处理漏标(重新标记)的数据时需要STW
- 混合收集:根据标记,找出存活数少的,即回收价值高的辣鸡区域,进行回收
- 说人话,跟其他的区别在于,这个区域分的更细,回收的辣鸡区域更少,速度更快
- 串行辣鸡收集器:
四种引用
- 强引用
有强引用就不会回收 - 软引用
有用但是非必须,oom之前可以回收 - 弱引用
碰到就回收 - 虚引用
跟踪对象状态,几乎没啥用
分析
- jmap -heap分析堆内存分配空间
- 配置jvm启动参数,oom时生成dump文件
- 用MAT工具分析dump文件