前面给你们讲解了 Java 虚拟的内存结构 以及 Java 虚拟机的垃圾回收机制,咱们更加明白了 Java 的内存管理机制,今天咱们来说讲 Java 虚拟机的另一个高频考点:类加载机制。java
JVM 的类加载过程分为加载、验证、准备、解析、初始化 5 个阶段。设计
加载阶段由类加载器进行负责,类加载器根据一个类的全限定名读取该类的二进制字节流到 JVM 内部,而后转换为一个对应的 java.lang.Class 对象实例;一个类由类加载器和类自己一块儿肯定,因此不一样类加载器加载同一个类获得的 java.lang.Class 也是不一样的。code
验证阶段负责验证类数据信息是否符合 JVM 规范,是不是一个有效的字节码文件。对象
准备阶段是正式为类变量(static 修饰的变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区进行分配。继承
这个阶段由两个容易产生混淆的概念须要强调一下,首先是这时候进行内存分配的仅包括类变量,而不包括实例变量,实例变量将会在对象实例化时随着对象一块儿分配在 Java 堆中。其次这里所说的初始值在没有被 final
修饰的时候都是数据类型的零值,只有相似 public static final int value = 1024
这样的状况下才回直接被赋值 123。内存
解析阶段是虚拟机将常量池内的「符号引用」替换为「直接引用」的过程。开发
初始化阶段负责将全部的 static 域按照程序指定操做对应执行(赋值 static 变量,执行 static 块)。get
上述阶段一般都是交叉混合容许,没有严格的前后执行顺序。虚拟机
站在 Java 虚拟机的角度讲,只存在两种不一样的类加载器:一种是启动类加载器,这个类加载器使用 C++ 语言实现,是虚拟机自身的一部分,另一种是全部其余的类加载器,这种类加载器都由 Java 语言实现,独立于虚拟机外部,而且所有继承自抽象类 java.lang.ClassLoader
。内存管理
双亲委派模型并非一个强制性的约束模型,而是 Java 设计者们推荐给开发者们的类加载器实现方式。它的工做过程是:若是一个类加载器收到了类加载的请求,它首先不会本身去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每个层次的类加载器都是如此,所以全部的加载请求最终都应该传送到顶层的类加载器中,只有当父加载器反馈本身完成这个加载请求的时候,子加载器才会尝试本身去加载。
使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是 Java 类随着它的类加载器一块儿具有了一种带有优先级的层次关系。
好比黑客定义一个 java.lang.String 类,该 String 类和系统 String 类有同样的功能,只是在某个方法好比 equels() 中加入了病毒代码,而且经过自定义类加载器加入 JVM 中,若是没有双亲委派模型,那么 JVM 就可能误觉得黑客编写的 String 类是系统 String 类,致使「病毒代码」最终被执行。而有了双亲委派模型,黑客定义的 java.lang.String 类就用于不会被加载进内存,由于最顶端的类加载器会加载系统的 String 类,最终自定义的类加载器没法加载 java.lang.String 类。
能够经过重写 loadClass() 方法,打破双亲委派模型。
最近的知识比较枯燥,但仍是咱们所必须了解的。
参考文献:《深刻理解 Java 虚拟机》