Java ClassLoader学习总结

来源:互联网 发布:网络林志玲是谁 编辑:程序博客网 时间:2024/05/18 23:28

ClassLoader的终极目标是干啥?

将一串二进制数据传递给虚拟机,虚拟机据此构建一个Class对象

为啥要有ClassLoader这个东西?

  • 可以更加灵活地控制类加载的过程(比如可以在运行时加载类从而实现程序的热更新)
  • 可以对class文件进行加密

ClassLoader的特点

全盘负责机制双亲委托模型

全盘负责机制

类加载器所创建对象的方法和构造方法可以引用其他类,为了确定引用的类,Java虚拟机将调用最初创建该类的ClassLoader的loadClass方法。

双亲委托模型

  • 对虚拟机来说,只有两种ClassLoader:BootstrapClassLoader(启动类加载器)其他所有的ClassLoader.BootstrapClassLoader是内置到虚拟机中的,典型的情况是用C++语言写的(有些虚拟机采用的是其他语言,甚至是Java语言).
  • 除了BootstrapClassLoader以外,每个ClassLoader都有一个父ClassLoader(一般用的组合而非继承方式实现的,也就是包含了一个父ClassLoader的引用),一个ClassLoader加载类时总是先委托父ClassLoader加载,如果父ClassLoader加载失败,自己再尝试加载.注意:由于BootstrapClassLoader是用C++语言实现的,所以其引用用null代替.
  • 从程序员的角度来看,ClassLoader可以分为四类:BootstrapClassLoader ExtensionClassLoader SystemClassLoader 自定义ClassLoader.BootstrapClassLoader加载Java语言核心类库,ExtensionClassLoader加载Java扩展类库,SystemClassLoader加载程序员编写的类库,一般为环境变量CLASSPATH下的类库.
  • ClassLoader的委托顺序为SystemClassLoader->ExtensionClassLoader->BootstrapClassLoader,通常自定义的ClassLoader委托SystemClassLoader,但其实也可以委托其他ClassLoader甚至是其他自定义ClassLoader.

如何自定义ClassLoader

  • 默认的loadClass方法族按以下顺序搜索类:

    1. 调用findLoadedClass(String)来检查是否已经加载类。
    2. 在父加载器上调用loadClass方法。如果父加载器为null,则使用虚拟机的内置类加载器BootstrapClassLoader。
    3. 调用findClass(String)方法查找类。
  • 基于上一条知识,自定义ClassLoader需要继承ClassLoader:

    1. 如果要破坏双亲委托模型,则重写loadClass方法族,并调用defineClass方法返回.
    2. 如果不需要破坏双亲委托模型,则重写findClass(String)方法,并调用defineClass方法返回.

注意点

  • 当且仅当两个类名字完全相同并且它们的ClassLoader相同,虚拟机才判定它们相同.每个Class对象都包含一个对定义它的ClassLoader的引用.
  • 笔者实现了两种代码自动更新的方法:
    1. 程序运行时修改自身一部分class文件,这样优点是不用自定义ClassLoader,简单方便,缺点是更新class文件的时机选择很重要,必须在所有需要更新的class文件都被加载(或者都没有被加载)时更新,否则容易出现代码版本不一致导致的严重问题.并且如果选择在所有需要更新的class文件加载完成后更新,需要重启程序更新才会生效.
    2. 自定义ClassLoader,优点是可以在程序运行时实现代码更新,缺点是较为复杂.实现要点:抽取可更新类的接口,并由SystemClassLoader加载此接口文件 可更新类实现上述接口,所以编译可更新类时要有一份接口文件的拷贝

参考资料

  • 深入理解Java虚拟机,第二版
  • Java API官方文档
  • http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/index.html
  • http://www.blogjava.net/lhulcn618/archive/2006/05/25/48230.html
0 0
原创粉丝点击