一、内存结构
1、方法区(线程共享)
主要用来存放类信息、static静态变量、final常量、运行时常量池
2、堆(线程共享)
主要存放的是数组、类的实例对象、字符串常量池
3、栈(线程私有)
局部变量表、操作数栈、动态链接、方法出口
4、本地方法栈(线程私有)
本地方法里面的局部变量表、操作数栈、动态链接、方法出口
5、程序计数器(线程私有)
计数器记录的是虚拟机字节码指令的地址,如果是 Natice方法,则为空
6、运行时常量池
它方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到常量池中。
7、字符串常量池
堆中的一块内存区域
二、类加载机制
1、类加载机制
1.1、加载
类加载阶段就是由类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例存储在堆区中,这个Class对象在日后就会作为方法区中该类的各种数据的访问入口
1.2、验证
这是虚拟机安全的重要保障,JVM需要核验字节信息是符合Java虚拟机规范的,否则就被认为是 VerifyError,这样就防止了恶意信息或者不合规信息危害JVM的运行,验证阶段有可能触发更多class的加载,保障虚拟机安全。
1.3、准备
创建类或者接口中的静态变量,并初始化静态变量的初始值
1.4、解析
在这一步会将常量池中的符号引用替换为直接引用
1.5、初始化
执行类初始化的代码逻辑,包括静态字段赋值的动作,以及执行类定义中的静态初始化块内的逻辑,编译器在编译阶段就会把这部分逻辑整理好,父类型的初始化逻辑优先于当前类型的逻辑
2、类加载器
2.1、启动类加载器/Bootstrap ClassLoader
在HotSpot虚拟机中,Bootstrap ClassLoader用C++语言编写并嵌入JVM内部,主要负载加载JAVA_HOME/lib目录中的所有类,或者加载由选项-Xbootcalsspath指定的路径下的类
2.2、拓展类加载器/ExtClasLoader
ExtClassLoader继承ClassLoader类,负载加载JAVA_HOME/lib/ext目录中的所有类型,或者由参数-Xbootclasspath指定路径中的所有类型
2.3、应用程序类加载器/AppClassLoader
ExtClassLoader继承ClassLoader类,负责加载用户类路径ClassPath下的所有类型,一般情况下为程序的默认类加载器
2.4、自定义加载器
Java虚拟机规范将所有继承抽象类java.lang.ClassLoader的类加载器,定义为自定义类加载器
3、双亲委派机制
当一个类加载器收到类加载任务时,立即将任务委派给它的父类加载器去执行,直至委派给最顶层的启动类加载器为止。如果父类加载器无法加载委派给它的类时,将类加载任务退回给它的下一级加载器去执行,双亲委派模型可以保证全限名指定的类,只被加载一次
三、垃圾回收
1、垃圾判断
1.1、可达性分析算法:当一个对象到GC Roots对象没有任何引用链相连时则证明此对象是不可用的。
1.2、可作为 GC Root 的对象包括以下几种:虚拟机栈(栈帧中的局部变量表)中引用的对象;方法区中类静态属性引用的对象;方法区中常量引用的对象;本地方法栈中Native方法引用的对象;
2、垃圾回收算法
2.1、标记清除
2.1.1、标记可以回收的对象然后清除两个阶段
2.1.2、效率不高、并且会产生大量的空间碎片
2.2、标记复制
2.2.1、将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
2.2.2、实践中会将新生代内存分为一块较大的Eden空间和两块较小的Survivor空间每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次地复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是 8:1,也就是每次新生代中可用内存空间为整个新生代容量的90% ( 80%+10% ),只有10% 的内存会被“浪费”。
2.2.3、效率高、浪费10%的内存空间
2.3、标记整理
2.3.1、让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,该垃圾回收算法适用于对象存活率高的场景。
2.3.2、效率高
3、垃圾回收器
3.1、Serial收集器(复制算法):新生代单线程收集器,标记和清理都是单线程,优点是简单高效
3.2、Serial Old收集器 (标记-整理算法):老年代单线程收集器,Serial收集器的老年代版本
3.3、ParNew收集器 (复制算法):新生代收并行集器,实际上是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现
3.4、Parallel Scavenge收集器(复制算法):新生代并行收集器,追求高吞吐量,高效利用 CPU
3.5、Parallel Old收集器 (标记-整理算法): 老年代并行收集器,吞吐量优先,Parallel Scavenge收集器的老年代版本
3.6、CMS收集器(标记-清除算法):老年代并行收集器,以获取最短回收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短GC回收停顿时间
3.7、G1(Garbage First)收集器 (标记-整理算法):Java堆并行收集器。G1回收的范围是整个Java堆(包括新生代,老年代),而前六种收集器回收的范围仅限于新生代或老年代
四、调优
1、常用工具
2、常用参数