ClassLoader 工作机制分析
一、ClassLoader工作内容
ClassLoader是类加载器,主要工作为:
(1)负责将Class加载到JVM。
(2)审查每个类应该由谁加载。(父优先的等级加载机制)
(3)将Class字节码重新解析成JVM统一要求的对象格式。
二、ClassLoader类中方法
ClassLoader中有四个方法,defineClass(),findClass(),loadClass(),resolveClass()。
(1)defineClass方法用来将byte字节流解析成JVM能够识别的Class对象。如果直接调用这个方法生成的Class对象,这个类的Class对象还没有resolve,这个resolve将会在这个对象真正实例化时才进行。
(2)findClass方法用来实现类的加载规则,从而取得要加载类的字节码。然后调用defineClass方法生成类的Class对象。
(3)loadClass方法可以获取某个类的class对象,例如:this.getClassLoader().loadClass(“class”)。这个loadClass还有重载方法,可以自己决定在什么时候解析这个类。
三、ClassLoader的等级加载机制
ClassLoader加载机制是一种“父优先”的等级加载机制。
整个JVM平台提供三层ClassLoader:
(1)Bootstrap ClassLoader:主要加载JVM自身工作需要的类,这个ClassLoader
完全由JVM控制,别人访问不到这个类。 Bootstrap ClassLoader仅是一个类的加载工具,没有更高一级的父加载器,也没有子加载器。
(2)ExtClassLoader:它是JVM自身的一部分,但并不是JVM亲自实现的。它服务的特性目标在 System.getProperty(“java.ext.dirs”)目录下。
(3)AppClassLoader :父类是ExtClassLoader,所有在System.getProperty(“java.class.path”)目录下的类都可以被这个类加载器加载,这个目录就是常用到的classpath。
四、JVM加载Class的两种方式
(1)隐式加载:通过JVM来自动加载需要的类到内存中。【例如:在类中继承或引用某个类时,JVM在解析当前这个类时发现引用的类不在内存中,就会自动将这些类加载到内存中】
(2)显示加载:在代码中通过ClassLoader类来加载这个类。【例如:调用loadClass()或者Class.forName()】
五、如何加载Class文件
第一阶段:找到.class文件,并把这个文件包含的字节码加载到内存中。
第二阶段:分为三个步骤(1)字节码验证(2)class类数据结构分析及相应的内存分配(3)符号表的链接
第三阶段:类中静态属性和初始化赋值,以及静态块的执行等。
六、常见的加载类错误分析
(1)ClassNotFoundExceptiom:当JVM要加载指定文件的字节码到内存时,并没有找到这个文件对应的字节码,也就是这个文件并不存在。解决的办法就是检查在当前的classpath目录下有没有指定的文件存在。
(2)NoClassDefFoundError:一般在第一次使用“java –cp example.jar Example”命令会用到,原因是在命令行里没有加类的包名,解决的办法是确保每一个类的引用的类都在当前的classpath下面,正确的写法是“java –cp example.jar net.packege.Example”
(3)UnsatisfiedLinkError:通常是JVM启动时,如果不小心把JVM的某个lib删除了,就可能报这个错。这个错误通常是在解析native标识的方法时JVM找不到对应的本机库文件时出现。
(4)ClassCastException:通常在程序中出现强制类型转换时出现这个错误。
(5)ExceptionInInitializerError:如果初始化器抛出一些Exception,而Exception类不是Error活着它的某个子类,那么就创建ExceptionInIntializerError类的一个新实例,并用Exception作为参考,用这个实例替代Exception。