略怂的类加载器
类加载:
class 是Java文件经过编译后的虚拟机指令,当需要用到某个类的时候,虚拟机会加载这个装有指令的.class 文件并转化为一个与目标类对应的java.lang.Class的对象实例到内存,这个过程叫做类加载。
类加载过程:
加载(loading)-> 链接(linking)-> 初始化(initialization)
其中 链接 又包括 验证(verification) -> 准备(preparation) ->解析(resolution)三个环节
类加载器:
分为 启动(Bootstrap)/扩展(Extension)/应用程序(APP)三种类加载器
启动类加载器:由C++实现,最顶层类加载器, 主要加载JVM自身需要的类,负责将%JAVA_HOME%/lib 下的核心类库或 -Xbootclasspath 指定路径下的类库加载到内存中
扩展类加载器:java实现,是Launcher 的静态内部类,负责加载%JAVA_HOME%/lib/ext 下类库或者 由 -Djava.ext.dir指定的类库
应用类加载器(系统类加载器):加载当前classpath 的所有类
双亲委派:
工作原理:啃老的类加载器,出事爹来抗,儿子找爸爸打坏蛋。如果一个类加载器有类加载请求时,他自个不会优先考虑解决,先找他的父类加载器,如果他父亲的父亲也就是他爷爷也还健在,那么他父亲会找到他爷爷去解决问题,直到找到最顶层的那个祖宗也就是启动类加载器,如果这个祖宗可以完成类加载任务,那么万事大吉,如果完不成,这时候父亲会对儿子语重心长的说:这事爹帮不了你,你自行解决。又会抛回给儿子类加载器,一层一层抛回去。
好处:类随着他的类加载器一起具备了优先级层级关系,可以避免类的重复加载。父亲已经解决了的事情,儿子坐享其成就好了,不需要再解决。
解决各个类加载器基础类同意问题,试想一下,假如开发者可以随便定义个类加载器去加载核心的api,这是不是灾难?
总而言之:好处两点,1.避免重复加载,2 ,更加安全。
自定义类加载器:
继承ClassLoader,重写findClass().在findClass中调用defineClass().
ClassLoader 几个重要方法:
方法 | 说明 |
getParent() | 返回该类加载器的父类加载器。 |
loadClass(String name) | 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。 |
findClass(String name) | 查找名称为 name的类,返回的结果是 java.lang.Class类的实例。 |
findLoadedClass(String name) | 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。 |
defineClass(String name, byte[] b, int off, int len) | 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的。 |