1. JVM是什么
JVM全称Java Virtual Machine,Java虚拟机。用来解析运行字节码程序,JVM消除平台差异性实现跨平台。
2 JVM运行时数据区
2.1 线程私有
2.1.1 栈(Stack)
- 栈是运行时的单位。
- 每个方法在执行的同时都会创建一个栈帧,用来存放局部变量,对象的引用之类的方法信息。
- 栈不存在垃圾回收,但是存在OOM和StackOverflowError。
2.1.2 本地方法栈(Native Method Stack)
虚拟机用到的 Native 方法,与底层相关。2.1.3 程序计数器(PC Register)
是每个线程都具有一个私有的程序计数器,因为JVM执行代码是一行一行的执行,所以需要计数器来记录当前执行的行数。
2.2 线程公有
2.2.1 堆(Heap)
- 堆区用来存储对象实例及数组值,可以认为java中所有通过new创建的对象都在此分配。
- 堆是GC执行垃圾回收的重点,在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除。
- 堆分为新生代和老年代。新生代的特点是每次垃圾回收时都有大量的对象需要被回收。老年代的特点是每次垃圾收集时只有少量对象需要被回收。
对象的分配过程
方法区是线程共享的区域,它一般用于储存与类相关的信息,像类信息、常量、静态变量,即编译器编译后的代码等
在jdk1.7中它的实现是永久代,缺点是经常会出现内存溢出。在jdk8中,实现为元空间,元空间直接使用本地内存,理论上电脑有多少内存,它就有多少内存,避免的内存溢出问题
运行时的常量池存放在元空间里,除了字符串常量池,字符串常量池存放在堆里。
3 类加载机制
3.1 类加载是什么
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内
在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口.
3.2 类加载器及双亲委派原则
双亲委派是当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务都会传递到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,才会尝试执行加载任务。
- 可以避免重复加载,保证java中类名的唯一性
- 保证java核心api中定义类型不会被随意替换,避免了核心API类不被修改
3.3 类的生命周期
加载
:根据查找路径找到响应的.class文件加载进内存,并为之创建Class对象验证
:保证被加载类的正确性准备
:为类的静态变量分配内存,并初始化为默认值。这一步和初始化有区别。比如static int a=1。那么到这部分配默认值是0,初始化的时候才是1.解析
:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;初始化
:对静态变量和静态代码块执行初始化工作。使用
卸载(垃圾回收)
4 垃圾回收机制
4.1 标记垃圾对象
4.2 GC分类
4.3 垃圾回收算法
4.3.1 标记-清除算法
采用从根集合进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象进行直接回收,不整理剩余对象会导致内存碎片。
4.3.2 复制算法
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。
4.3.3 标记-整理算法
标记整理是标记-清除算法的升级,标记清除分为标记和清除两个阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。但这样容易产生内存碎片,而升级的标记-整理不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存,充分利用内存空间。
4.3.4 分代收集算法
目前大部分JVM的垃圾收集器采用的算法。
新生代内存的回收(Minor GC)主要采用复制算法。
而对于老年代的回收(Major GC),大多采用标记-整理算法。
4.3 垃圾收集器
收集器 | 串行、并行or并发 | 生代 | 算法 | 目标 | 适用场景 |
---|---|---|---|---|---|
Serial | 串行 | 新生代 | 复制算法 | 响应速度优先 | 单CPU环境下的Client模式 |
Serial Old | 串行 | 老年代 | 标记-整理 | 响应速度优先 | 单CPU环境下的Client模式、CMS的后备预案 |
ParNew | 并行 | 新生代 | 复制算法 | 响应速度优先 | 多CPU环境时在Server模式下与CMS配合 |
Parallel Scavenge | 并行 | 新生代 | 复制算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
Parallel Old | 并行 | 老年代 | 标记-整理 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
CMS | 并发 | 老年代 | 标记-清除 | 响应速度优先 | 集中在互联网站或B/S系统服务端上的Java应用 |
G1 | 并发 | both | 标记-整理+复制算法 | 响应速度优先 | 面向服务端应用,将来替换CMS |
5 JVM调优
5.1 参数类型
5.2 JVM自带调优工具
jps | 主要用来输出JVM中运行的进程状态信息 |
---|---|
jstat | 显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据 |
jstack | 查看某个Java进程内的线程堆栈信息,根据堆栈信息我们可以定位到具体代码 |
jmap | 进程内存使用情况dump到文件中,再用jhat分析查看 |