Java类加载器

来源:互联网 发布:印度赶超中国 知乎 编辑:程序博客网 时间:2024/06/15 05:36

原文出处:http://javapapers.com/core-java/java-class-loader/

Java类加载器

java类加载器很简单,就是把java class文件加载到虚拟机。不需要掌握它的一堆理论知识,但是每个开发者都必须了解和知道它是怎样工作的。

好像NullPointerException一样,ClassNotFoundException也是一个非常普遍的错误。至少在你初学者阶段你可能遇到无数次ClassNotFoundException这样的错误。java类加载器就是这个错误的罪魁祸首。

java类加载器的层次结构

java类加载器可以概括地划分为以下类别:

Bootstrap类加载器:类似于java.lang,java.util这样的核心类会被Bootstrap类加载器加载,这些类是java运行环境的一部分,bootstrap类加载器是本地的实现,所以会因为不同的虚拟机而有所差别。

扩展(Extensions)类加载器:JAVA_HOME/jre/lib/ext 路径下面包含的jar包是用来扩展标准的核心类。扩展类加载器会加载ext文件夹下面的类。可以添加"ext"文件夹和jar文件到系统环境变量java.ext.dirs下并用扩展类加载器加载这些类。
系统(System)类加载器:系统类加载器加载classpath的java类。
你还会见到像java.net.URLClassLoader,java.security.SecureClassLoader这样的更多的类,他们都扩展于java.lang.ClassLoader.

这些类加载器之间都有一个层次关系。加载器可以从它层次之上的等级加载类。第一级是bootstrap类加载器,第二级是扩展类加载器,第三级是系统类加载器。

类的自引用(class self reference)

当一个java源文件编译成class,编译器会在class文件插入这样一个字段:public static final java.lang.Class class。

所以你可以通过classObj = ClassName.class来访问所有java类。

class对象最重要的是它包含了getClassLoader() 方法,它可以返回当前类的加载器,如果这个类是被bootstrap类加载器加载它会返回null;

java类加载器是怎样工作的?

类加载器首先会通过给定的类名去定位这个类然后从本地文件系统中读取这个类。因此它的加载过程是依赖平台的。
java.lang.classLoader默认是可以同时加载多个类的加载器,但是子类需要同时加载或构造时候加载。
当然也可以在运行时从网络上加载和构造类。classLoader类一个方法叫defineClass,它可以逐个字节读取然后加载一个类。

父类加载器(Class Loader Parent)

除bootstrap类加载器外,所有的类加载器都有一个父类加载器,这个父的关系与父—子的继承关系是不一样的。每个类加载器都与他的父类加载器联系在一起。
当一个类加载器需要加载一个类时候,首先他会把这个任务委托给它的父类加载器,然后这个父类加载器收到指令然后把再传给它的父类加载器。在这个链状层次的顶端是bootstrap类加载器。

当一个类加载器实例被创建,通过它的构造器他的父类加载器会与他关
联在一起。


类加载器法则1(Class Loader Rule 1)

一个类只能被加载一次到虚拟机中。
这个法则中的“一个类”是指什么呢?一个类的唯一性是这样定义的,这个类和把这个类加载到虚拟机中的类加载器实例组成了一个类的唯一性。一个类通常以它的全限定名(package,calssname)定义。所以当一个类被加载到虚拟机,会有这样一个条目(package,calssname,classloader).所以同样的类可以被不同的类加载器加载两次到虚拟机中。




原创粉丝点击