ITPub博客

首页 > 应用开发 > Java > 深入理解JVM之类加载

深入理解JVM之类加载

原创 Java 作者:541732025 时间:2014-03-25 18:53:20 0 删除 编辑

JVM将类加载过程分为三个步骤:装载、链接、初始化。装载、链接完成后,即可将二进制字节码转换为Class对象,
初始化过程不是加载类时必须触发的,只要求在初次使用对象前执行即可,初始化主要给静态变量赋值、调用()等
一,装载(load)
JVM通过类的全限定名(com.sun.HelloWorld)及类加载器(ClassLoader实例)完成类的加载,相应地,
也是用这两个元素来标识一个被加载了的类:类的全限定名 + ClassLoader实例ID

二,链接
对二进制字节码的格式进行校验、初始化类中的静态变量、解析类中调用的接口、类。
校验过程中,如果格式不符则抛出VerifyError,如果碰到要引用其它接口或类,也会进行加载,如果加载过程失败,
则会抛出NoClassDefFoundError。
完成校验以后,JVM初始化类中的静态变量,并将其赋值为默认值。
最后对类中所有属性、方法进行校验,以确保其要调用的属性、方法存在,以及具备相应的权限(如public、private等),
如果这个阶段失败,可能会造成NoSuchMethodError、NoSuchFieldError等错误。

三,初始化
初始化过程即执行类中的静态初始化代码、构造代码及静态属性的初始化,以下几种情况会触发初始化过程:
1,调用new
2,反射调用了类中的方法
3,子类调用了初始化
4,JVM启动过程中指定的初始化类

四,类加载器
JVM的类加载通过ClassLoader及其子类来完成,分为Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader及User-Defined ClassLoader,除了Bootstrap外,剩下3个都是有父子层级关系的。
Bootstrap,此类不是ClassLoader的子类,代码中无法拿到这个对象,JDK启动时会初始化该ClassLoader,并由它加载$JAVA_HOME/jre/rt.jar中所有class的加载,这些class是java规范定义的所有接口及实现(java.lang, java.util等)
Extension加载$JAVA_HOME/jre/ext/*.jar。
System加载启动参数中指定的Classpath中的jar,简言之,用户写的class会由它加载,Sun JDK中对应的实现类为AppClassLoader
User-Defined ClassLoader是开发人员自行实现的ClassLoader,可用于加载非classpath中的jar,如从网络上下载的jar或二进制。
之前说过,ClassLoader是有父子层级关系的,当加载class时,首先会去已加载的class中查找,如果有,直接返回,否则判断parentClassLoader是否存在,存在,调用parent . loadClass,不存在,调用findBootstrapClassOrNull。如果最后还是找不到,则调用findClass,该方法默认直接throw new ClassNotFoundException,需要ClassLoader子类自己覆盖。
但加载时也可以不采用以上顺序,可以直接在当前的ClassLoader中寻找,如Class.forName(),JVM会直接通过当前ClassLoader(也就是执行Class.forName所在类的ClassLoader,caller.getClassLoader0() native方法)加载Class。
由于JVM是采用类全限定名+ClassLoader实例来判断是否加载了某个类,所以,如果直接从当前classLoader直接加载的话,
会造成树上多个不同的classloader中都加载了某class(某处Class.forName,某处直接new),且这些Class的实例对象都不同。JVM会保证同一个ClassLoader实例中只能加载一次同样名称的Class,因此可以借助此来实现类隔离的需求。
但也会有问题,例如ClassCastException,因此在加载类时,尽量保证从根到最下层的ClassLoader上的Class只加载一次。
当ClassLoader在整个树中都没找到Class对象,则抛出ClassNotFoundException

类加载的常见异常:
1,ClassNotFoundException:ClassLoader加载类时未找到该类。
2,NoClassDefFoundError:在加载的类中引用到其它的类不存在,或者加载引用的类失败。
3,ClassCastException:两个对象的Class有不同的ClassLoader加载。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28912557/viewspace-1129390/,如需转载,请注明出处,否则将追究法律责任。

上一篇: Spring RMI配置
请登录后发表评论 登录
全部评论

注册时间:2013-05-23

  • 博文量
    127
  • 访问量
    482772