类加载机制
也即是从I/O或者网络流中读取字节码,转换识别成JVM的Class对象的过程。
ClassLoader类实现的类加载。
findeClass方法查找字节码class
defineClass方法将byte字节流解析成JVM能识别的Class对象
resolveClassJVM真正链接该类
loadClass包含以上的步骤,直接加载类
ClassLoader层级
Bootstrap ClassLoader 负责加载java基础类,服务于JVM自身的,不受上面的加载限制,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar等
Extension ClassLoader 负责加载java扩展类,非JVM内部的扩展,主要是 %JRE_HOME/lib/ext 目录下的jar和class
App ClassLoader 负责加载当前java程序的,也就是classpath中的类。
类加载类型
隐式加载
通过JVM自动加载需要的类到内存中的方式,比如类中存在继承或者引用的时候,如果JVM发现该类不存在内存中,就会隐式加载到内存中。
显示加载
通过代码中调用ClassLoader类来加载。
Class 类中的 forName 方法
ClassLoader 类中的 findSystemClass 方法
ClassLoader 类中的 loadClass 方法
常见的类加载错误
ClassNotFoundException/NoClassDefFoundError
原因:当JVM显示的加载指定类文件的字节码到内存时,并没有找到对应的字节码。其实这个加载字节码的过程就是InputStream读取指定文件流到内存的过程。(NoClassDefFoundError容易出现在命令行操作过程中)
解决办法:
查看当前的classpath下面有没有指定的文件存在。
获取当前classpath的绝对URL路径
this.getClass().getResource("");
this.getClass() .getClassLoader().getResource("");
ClassLoader.getSystemResource("");
获取当前class的类路径目录
- this.getClass().getResource("");
Web应用程序的根目录的绝对路径
- ServletActionContext.getServletContext().getRealPath(“/”);
UnsatisfiedLinkError
当调用本机方法native时,类装入器会尝试装入定义了该方法的本机库。
如果 Java 虚拟机找不到和它对应的本机库,就会抛出该异常。
通常是jvm某个包被删除了,或者某个动态链接库被删除了就会出现这个异常。
原文链接:Java类加载相关学习笔记,转载请注明来源!