JVM
结构
线程共享:堆(存储对象、数组)、方法区(1.8后变为元空间,用本地内存,存储类信息、常量池、静态变量)
线程独占:程序计数器(字节码的行号指示器)、本地方法栈、jvm栈(每个方法执行都创建一个栈帧,其中存储了局部变量表(基本数据、对象的引用)、操作数栈、方法出口)
类加载
加载过程
- 加载:将字节码文件载入到内存,在方法区为其建立java.lang.class对象
- 连接
验证
准备:为类变量分配内存设置初始值(默认值)
解析:将符号引用转为直接引用 - 初始化
父类代码块 父构造器 子代码块 子构造器 父静态方法 子静态方法
类加载器
任务是根据类的全限定名来读取此类的二进制字节流到 JVM 中,然后转换成一个与目标类对象的java.lang.Class 对象的实例
- 启动类加载器Bootstrap ClassLoader:%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等
- 扩展类加载器Extention ClassLoader:%JRE_HOME%\lib\ext目录下的jar包和class文件
- 系统类加载器Appclass Loader也称为SystemAppClass:加载当前应用的classpath的所有类
双亲委派原则:当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务都会传递到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,才会尝试执行加载任务。
1、可以避免类的重复加载,当父亲已经加载了该类的时候,就没有必要子类加载器(ClassLoader)再加载一次
2、Java核心API中定义类型不会被随意替换,假设通过网路传递一个名为java.lang.Integer的类,通过双亲委派的的模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字类,发现该类已经被加载,并不会重新加载网络传递过来的java.lang.Integer.而之际返回已经加载过的Integer.class,这样便可以防止核心API库被随意篡改。
自定义类加载器
(问:自定义类加载器怎么实现,其中哪个方法走双亲委派模型,(实现findclass方法,一般用defineclass加载外部类),如何才能不走双亲委派。(重写loadclass方法))
三个重要函数:loadClass,findClass,defineClass
loadClass:调用父类加载器的loadClass,加载失败则调用自己的findClass方法
findClass:根据名称读取文件存入字节数组
defineClass:把一个字节数组转为Class对象
- 继承ClassLoader类
- 覆盖findClass(String className)方法
垃圾回收算法
判断对象是否存活:引用计数法(无法解决循环引用)、可达性分析(gcroots:jvm栈中、native方法栈、方法区中常量、类静态属性引用的对象)
回收算法:
- 标记清除法:先从gcroots遍历然后标记到达的对象,然后遍历存活对象,没有被标记的被清除;容易产生大量内存碎片
- 复制算法:划分使用空间和保留空间,将存活对象复制到保留空间,清除使用空间;适用于存活对象少的情况
- 标记整理(标记压缩):将存活对象移动到内存空间一端,然后回收边界外的内存
jvm采用分代收集算法,年轻代用复制算法,老年代用标记整理算法。
新生代晋升策略
动态年龄判断、大对象直接晋升、担保(minorgc后空间不足以存放存活对象)、长时间存活的
何时发生full gc
老年代空间不足、担保后不足、class信息过多永久代空间不足
垃圾回收器
可以根据自己的需求组合出不同年代使用的收集器
1.Serial/Serial Old收集器 是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿stop the world
2.ParNew收集器 是Serial收集器的多线程版本,使用多个线程进行垃圾收集
3.Parallel Scavenge收集器 是一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量
4.Parallel Old收集器 是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法
5.CMS(Current Mark Sweep)收集器 是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法,初始标记stw,其他标记过程和用户线程并发执行
6.G1收集器 是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型,优先选择回收价值最大的Region