JVM内存模型
- 堆:主要用于存放new出的对象和数组,可通过GC回收。
- 虚拟机栈:线程私有栈,存着栈帧,主要是局部变量表,也就是基本数据类型和对象引用等信息。
- 本地方法栈:用于存放Native方法。
- 程序计数器:用于标识程序执行的字节码指令地址,线程私有。
- 方法区(非堆):主要存储类的信息、常量池、静态变量等。
java7之前叫永久代,java8之后改为了元空间,使用本地内存,理论上无上限,但一般使用时需要指定元空间大小。
类加载流程
通常分为7个流程:加载、验证、准备、解析、初始化、使用、卸载。
- 加载:通过类名获取二进制字节流,将字节流转换为方法区的运行时数据结构,生成class对象作为访问入口。由类加载器完成加载。
- 验证:检查字节码合法性。
- 准备:为静态变量分配内存并附默认值。
- 解析:将符号引用替换为直接引用。
- 初始化:执行clinit方法,按顺序初始化静态变量和静态代码块。
- 使用:类完成初始化后进入运行阶段,可被实例化或调用方法。
- 卸载:当类无实例、引用且类加载器被回收时,JVM卸载该类。
服务中用到的JVM参数(常见)
- -Xms、-Xmx:用于配置初始堆大小和最大堆大小。
- XX:MetaspaceSize=32m -XX:MaxMetaspaceSize=256m:用于控制初始元空间大小和最大元空间大小。
- -XX:+HeapDumpOnOutOfMemoryError:用于使服务出现OOM异常后生成dump文件。
- XX:NewRatio:用于配置新生代老年代比例。
垃圾收集器
Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1、ZGC。
垃圾回收算法
标记-清除:内存碎片较多,很少使用。 复制:一般新生代使用。 标记-整理:一般老年代使用。 分代收集:典型代表CMS收集器,G1收集器的分区粒度更细。
类加载器
- 启动类加载器(BootStrap ClassLoader):加载如rt包下面的类。
- 扩展类加载器(Extension ClassLoader):加载如javax包下面的类。
- 应用类加载器(Application ClassLoader):加载classpath下的类。
- 自定义加载器(Customize ClassLoader):自定义类继承ClassLoader重写findClass方法加载类。 JDK9之后扩展类加载器变成了平台类加载器(Platform ClassLoader)。
双亲委派机制
一个类加载器加载某个类的时候,会优先委派父加载器处理,父加载器不能完成加载时自己才会进行加载。可保障核心类库的安全性。
如何破坏双亲委派机制
双亲委派机制历史上有三次破坏。
- 自定义加载器重写loadClass方法,跳过父类委托。
- 通过SPI机制进行破坏。
- 通过OSGi模块化加载。