Java的类(类)加载程序主要在类加载的“加载阶段”中工作。它的主要功能是从系统外部获得类的二进制数据流。
关于类(类)的文件结构:Java的类(类)文件结构详细说明;类加载过程的详细说明:Java的类(类)加载过程。
分类加载机制有三种类型:如下:
Java的JVM在加载时默认情况下使用双党约会机制和缓存机制。
对于任何类,加载的类加载程序,此类本身在Java Virtual Machine中建立了其独特性。eastclass Loader具有独立的类名称空间。也就是说:只要两个类是“等于”的,只要这两个类是由同一类加载程序加载的,否则,即使这两个类来自同一类文件,它们也与同一类文件相同,并且与同一类文件相同。机器已加载。只要其类负载器的加载程序不同,这两个类必须不同。
此处引用的“均等”,包括类班级的类对象的equals()方法,类对象的equals()方法的返回结果,issignablefrom()方法,islnstance()方法和对象对象使用关键字实例之间的关系的判断。如果没有注意到类加载程序的效果,则可能会在某些情况下会令人困惑。以下代码演示了不同类加载程序对Instanceof关键字操作结果的影响。
以下情况:
根据“ Java虚拟机规范Javase8”,Java虚拟机支持两种不同类型的加载器:
从Java开发人员的角度来看,类加载程序可以大致分为以下三个类别:
Bootstrap classloader,也称为root Loader/Guide Class Loader。它是在Java虚拟机启动之后初始化的,并且用于加载Java的核心库,例如< JAVA_HOME >/jre/lib/rt.jar班级中的所有课程,例如Java.Time。,Java.util。,Java.nio。,Java.lang。,各种库的JUC软件包。
Java程序不能直接引用启动加载程序。当用户编写自定义类加载程序时,如果需要将加载请求分配给启动类加载程序,请改用null。
以下程序可以使启动加载程序加载核心库,您将看到该计算机中安装的JAVA环境变量指定的JDK中提供的核心JAR软件包路径:::::::
我的机器的输出如下:
Extension ClassLoader,用于加载Java的扩展库。此加载程序由Sun.Misc.Misc.Launcher $ ExtClassLoader实现,该库负载负载< JAVA_HOME >在Jribext目录或所有类库中(例如Javax。*在Javax的开头。Java语言。
获取扩展装载器加载的JAR软件包:
应用程序classloader,也称为系统加载程序。此类加载程序由Sun.misc.launcher $ appClassLoader实现。
此类加载程序是ClassLoader中GetSystemClassLoader()方法的返回值,因此通常称为System Class Loader。它负责加载在用户路径(ClassPath)上指定的类库。开发人员可以使用此类加载程序。如果应用程序不自定义自己的类加载程序,则通常是程序中的默认类加载程序。
我们的应用程序在这三个类加载程序中相互加载。如有必要,您还可以添加自己定义的类加载程序。开发人员可以通过继承Java.lang.classloader类,调用decteClass()方法来重写FindClass()方法,以实现自己的类加载程序以满足一些特殊的需求。
为什么有自定义类加载程序?
以上装载机之间的关系通常如下图所示:
上图中的类加载程序之间的分层关系称为类加载程序的两个 - 父母约会模型。在顶部 - 级启动类加载程序中,两个级别的加载程序应具有自己的父母加载程序。这里的加载程序之间的父母和儿子通常无法实现继承关系,而是使用组合关系来重用父母加载程序的代码。
父母委托模型的工作过程是:如果类加载程序从类加载程序接收请求,它将首先尝试自行加载此类。顶层上的类加载器。子加载类将尝试加载自己)。
使用双极预约模型的优点是,Java类与其类加载器具有首选关系。通过这种级别,它可以避免重复的类。当父亲加载此类课程后,该类已被加载。无需再次加载。
其次,考虑到安全因素,Java Core API中的定义类型将不会随意替换。在Core Java API中找到了该名称的类,发现该类已被加载并且不会重新加载Java。lang.integer,将再次加载,并直接返回加载的整数。class,这可以防止核心API防止库中的核心API随意篡改。
双边任命模型对于确保Java计划的稳定性非常重要,但其实施非常简单。双列斯分配的代码集中在Java.lang.lang.classloader的LoadClass()方法中:检查是否首先加载了类失败,抛出ClassNotFoundException异常后,然后调用您的Final()方法进行加载。
双边约会模型不是强制性约束模型,而是一种实现Java Designer推荐给开发人员推荐的类型加载器的方法。Java世界中的大多数类加载程序都遵循此模型,但是有例外。到目前为止,两个父母的任命模型主要具有3个大型“损坏”。
两父母任命模型的第一个“被摧毁”实际上发生在两个父母任命模型之前,也就是说,在发布JDK1.2.的情况下,由于JDK1.2之后是在JDK1.2的发布之前。班级加载程序和抽象类Java.lang.ClassLoader已经存在JDK1.0.Code时,Java设计人员在介绍两个 - 父母的任命模型时必须做出一些妥协。2添加了一个新的Proceted方法FindClass()。在此之前,用户继承java.lang.classloader的唯一目的是重写loadClass()方法,因为当加载虚拟类时,加载程序的私有方法称为LoadClassInternal(),此方法的唯一逻辑是要调用您的LoadClass().jdk1.2将不再倡导用户再次涵盖LoadClass()方法。它应该为FindClass()方法写下自己类的逻辑。在LoadClass()Method的逻辑中,请调用您的FindClass()方法以完成负载,以便新编写的加载程序可以与双边约会模型保持一致。
两个父母任命模型的第二个“破坏”是由该模型本身的缺陷引起的。两个 - 父母的任命模型解决了每个类的基本类别的基本类别的问题(基本类是由上层上层执行的上层上层加载器执行的,而基本类称为“基础”“因为它们总是用作API,称为代码调用。但是,如果基本类需要调用用户的代码,我该怎么办?
这不是不可能的事情。一个典型的例子是JNDI服务。它的代码由启动类加载程序(RT.JAR)加载,并且需要调用独立制造商在应用程序中部署的JNDI接口提供商(SPI,服务提供商接口)的代码如果启动 - up类加载程序不能“知道”一些代码,我会做吗?
为了解决这一难题,Java设计团队必须引入一个不太优雅的设计:线程上下文classLoader。可以通过Java.lang.thread类的SetContContextClassLoader()方法设置此类加载程序。如果在创建线程时未设置它,它将从父螺纹继承一个。如果应用程序的全局范围中没有设置,则不会设置它。然后,此类加载程序是默认情况下的应用程序类加载程序。在线程上下文类加载程序中,JNDI服务使用此线程上下文上下文加载程序来加载所需SPI代码,即父母加载程序请求子类以完成类加载操作。这种行为实际上是开放的。两个父母约会模型的层次结构扭转了类加载器的使用,这违反了两个父母的任命模型,但这也是无助的。所有涉及Java中SPI的装载运动基本上都是spis使用此方法,例如JNDI,JDBC,JCE,JAXB和JBI。
两个父母任命模型的第三个“破坏”是由用户对程序的动态追求引起的,例如OSGI的出现。在OSGI环境中,加载器的类型不再是Binsea预约模型中的树结构,但进一步发展为网络结构。
作者:Liu Java