Java 类加载器是Java 运行时环境的一部分,它可以将 Java 类动态加载到Java 虚拟机中。由于类加载器,Java 运行时系统不需要了解文件和文件系统。
Java 类不会一次全部加载到内存中,而是在应用程序需要时加载。此时,JRE调用Java ClassLoader,这些 ClassLoader 将类动态加载到内存中。
并非所有类都由单个 ClassLoader 加载。根据类的类型和类的路径,决定加载该特定类的 ClassLoader。要了解加载类的 ClassLoader,请使用getClassLoader()方法。所有类都根据它们的名称加载,如果找不到这些类中的任何一个,则返回NoClassDefFoundError或ClassNotFoundException。
Java 类加载器分为三种类型:
BootStrap ClassLoader:Bootstrap ClassLoader是一个机器代码,它在 JVM 调用它时启动操作。它不是一个java类。它的工作是加载第一个纯Java ClassLoader。Bootstrap ClassLoader 从rt.jar位置加载类。Bootstrap ClassLoader 没有任何父 ClassLoader。它也被称为Primodial ClassLoader。
Extension ClassLoader: Extension ClassLoader 是 Bootstrap ClassLoader 的子类,从各自的 JDK Extension 库中加载核心 java 类的扩展。它从jre/lib/ext目录或系统属性java.ext.dirs指向的任何其他目录加载文件。
系统类加载器:应用程序类加载器也称为系统类加载器。它加载在环境变量CLASSPATH、-classpath 或 -cp 命令行选项中找到的应用程序类型类。Application ClassLoader 是 Extension ClassLoader 的子类。
注意:ClassLoader 委托层次模型总是按照 Application ClassLoader->Extension ClassLoader->Bootstrap ClassLoader 的顺序运行。Bootstrap ClassLoader 总是被赋予更高的优先级,其次是 Extension ClassLoader,然后是 Application ClassLoader。
功能原则是Java 类加载器工作的一组规则或特性。功能的三个原则,它们是:
委托模型:Java 虚拟机和 Java 类加载器使用一种称为委托层次算法的算法将类加载到 Java 文件中。
ClassLoader 基于委托模型给出的一组操作工作。他们是:
ClassLoader 始终遵循委托层次原则。
每当 JVM 遇到一个类时,它都会检查该类是否已经加载。
如果该类已经加载到方法区域中,则 JVM 继续执行。
如果该类不在方法区域中,则 JVM 要求 Java ClassLoader Sub-System 加载该特定类,然后 ClassLoader 子系统将控制权移交给Application ClassLoader。
然后,Application ClassLoader 将请求委托给 Extension ClassLoader,而Extension ClassLoader又将请求委托给Bootstrap ClassLoader。
Bootstrap ClassLoader 将在 Bootstrap 类路径(JDK/JRE/LIB)中搜索。如果类可用,则加载它,否则将请求委托给 Extension ClassLoader。
Extension ClassLoader 在 Extension Classpath(JDK/JRE/LIB/EXT) 中搜索类。如果类可用,则加载它,否则将请求委托给 Application ClassLoader。
Application ClassLoader 在 Application Classpath 中搜索类。如果该类可用,则加载它,如果不可用,则生成ClassNotFoundException异常。
可见性原则:可见性原则指出,由父类加载器加载的类对子类加载器可见,但由子类加载器加载的类对父类加载器不可见。假设一个类 GEEKS.class 已被 Extension ClassLoader 加载,那么该类仅对 Extension ClassLoader 和 Application ClassLoader 可见,而对 Bootstrap ClassLoader 不可见。如果再次尝试使用 Bootstrap ClassLoader 加载该类,则会给出异常java.lang.ClassNotFoundException。
唯一性属性:唯一性属性确保类是唯一的并且没有类的重复。这也确保了父类加载器加载的类不会被子类加载器加载。如果父类加载器无法找到该类,那么只有当前实例会尝试自己这样做。
在 JVM 请求类之后,需要执行几个步骤来加载类。类是根据委托模型加载的,但有一些重要的方法或函数在加载类中起着至关重要的作用。
loadClass(String name, boolean resolve):该方法用于加载JVM引用的类。它将类的名称作为参数。这是 loadClass(String, boolean) 类型。
defineClass():defineClass() 方法是最终方法,不能被覆盖。此方法用于将字节数组定义为类的实例。如果类无效,则抛出ClassFormatError。
findClass(String name):此方法用于查找指定的类。此方法只查找但不加载类。
findLoadedClass(String name):该方法用于验证 JVM 引用的 Class 之前是否已加载。
Class.forName(String name, boolean initialize, ClassLoader loader):该方法用于加载类以及初始化类。此方法还提供了选择任何一个 ClassLoader 的选项。如果 ClassLoader 参数为 NULL,则使用 Bootstrap ClassLoader。
示例:在加载类之前执行以下代码:
protected synchronized Class<?>
loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
try {
if (c == NULL) {
if (parent != NULL) {
c = parent.loadClass(name, false);
}
else {
c = findBootstrapClass0(name);
}
}
catch (ClassNotFoundException e)
{
System.out.println(e);
}
}
}
注意:如果一个类已经被加载,它会返回它。否则,它将对新类的搜索委托给父类加载器。如果父类加载器没有找到该类,loadClass()调用方法findClass()来查找并加载该类。如果父ClassLoader没有找到该类, findClass()方法会在当前ClassLoader中搜索该类。如果大家想了解更多相关知识,不妨来关注一下动力节点的Java在线学习,里面的课程内容从入门到精通,很适合零基础的小伙伴学习,希望对大家能够有所帮助。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习