一条大路通向JVM
基本概念
JVM是可运行Java代码的假象计算机,包括一套字节码指令集,一组寄存器,一个栈,一个垃圾回收,堆和一个存储方法域,JVM是运行在操作系统之上,它与硬件没有直接的交互
JVM内存模型
JVM运行时内存区域划分,哪些线程私有
类加载机制
加载
把A.class字节码文件从各个来源通过类加载器装载入内存,然后将该字节流所代表的静态数据结构转化为方法区(和堆一样,被所有线程共享)中运行的数据结构,并且在堆内存中生成一个A class对象作为访问方法区数据结构的入口,当第二次还需要创建A对象的时候,此时堆中已经有了A class对象就不会再生成第二个了,一个类只产生一个class对象
链接
-
验证
确保当前class文件的字节流所含的内容符合当前JVM的规范要求,并且不会出现危害JVM自身安全的代码 -
准备
当一个class文件的字节流通过验证,就开始为该对象的静态变量分配内存和初始值(非静态变量也会被赋予初始值)
二者都会被赋予0的初始值 -
解析
在常量池中找到类,接口,方法,字段的符号引用,并将其替换成直接引用的过程
例如调用方法get() ,这个方法地址为44832,那么“get”就是符号引用 , 地址44832就是直接引用
初始化
这个阶段主要是对类变量初始化,是执行类构造器<client>的过程,<client>方法是由编译器自动收集类中的变量的赋值操作和静态语句块中的语句合并而成的,虚拟机会保证子<client>方法执行之前,父类的<client>方法已经执行完毕,如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成<client>方法
类加载器
启动类加载器
加载jre/lib 下面的jar文件,如rt.jar
扩展类加载器
负责加载我们放到 jre/lib/ext/ 目录下面的 jar 包,这就是所谓的 extension 机制。
应用程序类加载器
负责加载用户路径(classpath)上的类库,JVM通过双亲委派模型进行类的加载
如何自定义实现类加载器
- 继承ClassLoader类
- 覆盖findClass方法
ClassLoader超类的loadClass方法用于将类的加载操作委托给其父类加载器去进行,只有当该类尚未加载并且父类加载器也无法加载该类时,才调用findClass方法。
如果要实现该方法,必须做到以下几点:
1.为来自本地文件系统或者其他来源的类加载其字节码。
2.调用ClassLoader超类的defineClass方法,向虚拟机提供字节码。
具体实现 :https://www.jianshu.com/p/e2c7a1335e16
双亲委派模型
当类加载器(Class-Loader)试图加载某个类型的时候,除非父加载器找不到相应类型,否则尽量将这个任务代理给当前加载器的父加载器去做,因此所有的加载请求都应该传送到启动类加载器中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。使用委派模型的目的是避免重复加载 Java 类型。