1.1 类加载机制原理
1)层级结构,分为4层(自定义->应用程序类->扩展类->启动类),启动类用C++
2)双亲委派模式(从下往上委托,从上往下加载,为统一基础类)(见源码)
a)可见性限制(下层可以看到上层类加载器中的类,反之不行)
b)类加载器只能加载不能卸载类
c)对于特定的类加载而言,一个类只能被加载一次,可以被不同的类加载器加载
1.2 JVM内存模型
1)程序计数器(线程私有)
可以看成当前线程执行的字节码行号指示器。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成。例如:多线程切换后能恢复到正确的执行位置,每条线程都有一个独立的程序计数器,独立存储。
唯一一个没有规定任何OutOfMemoryError的区域
2)Java虚拟机栈(线程私有)
虚拟机栈描述的java方法执行的内存模型:方法调用入栈,方法结束出栈。
3)本地方法栈Native Method Stacks(私有线程)
为虚拟机使用到的Native方法服务
4)堆(线程共享)
存放对象实例。垃圾收集器主要管理的是java堆,物理上可以不连续。
5)方法区(线程共享)
用于存储类信息、常量、静态变量、即时编译后的代码等数据。
6)常量池(线程共享)
是方法区的一部分,在运行期间将新的常量放入池中。
1.3 垃圾回收算法
怎么标记没有引用的对象:
1)引用计数
有引用就+1,引用失效就-1,会出现循环引用A-B,B-A,虚拟机不使用
2)可达性分析
从Gc Roots出发,往下搜索并标记,未标记的对象就不会删除
整理的算法:
1)标记清理
先标记,后清理。缺点:收集后空间离散,不利于连续空间分配(内存碎片)。
2)标记整理——老年代
先标记,后清理,再合并。优点:收集后空间连续,适用于存活率较高场景。
3)复制——新生代
将内存划成相同2块,每次只使用其中一块,当一块中内存使用完了,就将存活的对象复制到另一块,清除已使用完的内存,交替使用。优点:只移动项顶指针,按顺序分配,实现简单;缺点:内存使用只有一半,当存活率较大时,效率低。适用于存活率较低场景,改进后(Eden区80%,FromSpace10%,ToSpace区10%)
4)分代收集(存活周期)
将java堆分为新生代和老年代,根据各个年代的特点适用不同的收集。
新生代(minor GC):大批对象死去,少量存活,只需少量存活复制
老年代(full GC):存活率较高,没有额外空间分配,使用标记清理或标记整理。