Java程序运行图:
上一篇玩命学JVM(一)—认识JVM和字节码文件我们简单认识了 JVM 和字节码文件。那JVM是如何使用字节码文件的呢?从上图清晰地可以看到,JVM 通过类加载器完成了这一过程。
接下来我们对思维导图中重难点部分做补充。
1. 是什么?类的加载就是将 .class 文件的二进制数据读入到内存中,将其放在 JVM 的运行时数据区的方法区内。然后在堆区内创建一个 java.lang.Class 对象,用于封装类在方法区内的数据结构。
5. 双亲委派模型双亲委派模型图如下:
对于“双亲委派模型”,首先需要纠正一点,“双亲”并不是说它有“两个亲”。实际上行“双亲委派模型”和“双”毫无关系,只和“亲”有关系。
其实“双亲”是翻译的一个错误,原文出处是“parent”,被翻译成了“双亲”,在计算机领域更常见的说法是“父节点”。所以如果将“双亲委派模型”改为“父委派模型”,应该更好理解。
结合实际的类加载器来说,就是:
每个类加载器都会向上找自己父类加载器尝试完成类加载;
父加载器加载失败会向下找加载器尝试加载。
如图:
接下来我们从源码上来分析下 双亲委派模型
除Bootstrap ClassLoader外,其它的类加载器都是ClassLoader的子类。加载类的方法为loadClass,查看源码可发现,loadClass在ClassLoader中有具体的实现,且在各个子类中都没有被覆盖。
先介绍三个重要的函数,对后续的源码阅读有帮助:
loadClass:调用父类加载器的loadClass,加载失败则调用自己的findClass方法。
findClass:根据名称读取文件存入字节数组。
defineClass:把一个字节数组转为Class对象。
所谓的双亲委派模型,就是利用了loadClass只在父类中实现了这一点。
自定义类加载器自定义类加载主要有两种方式:
遵守双亲委派模型:继承ClassLoader,重写findClass()方法。
破坏双亲委派模型:继承ClassLoader,重写loadClass()方法。 通常我们推荐采用第一种方法自定义类加载器,最大程度上的遵守双亲委派模型。
我们看一下实现步骤
(1)创建一个类继承ClassLoader抽象类
(2)重写findClass()方法
(3)在findClass()方法中调用defineClass()
第一步,自定义一个实体类Person.java,我把它编译后的Person.class放在D盘根目录下:
package com.xrq.classloader; public class Person { private String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String toString() { return "I am a person, my name is " + name; } }