什么是Java ClassLoader?

时间:2010-03-11 11:50:03

标签: java classloader

在一些简单的句子中,什么是Java ClassLoader,何时使用以及为什么?

好的,我读了一篇wiki文章。 ClassLoader加载类。好。因此,如果我包含jar文件并导入,则ClassLoader可以完成这项任务。

为什么我要打扰这个ClassLoader?我从来没有用它,也不知道它存在。

问题是,为什么ClassLoader类存在?而且,你如何在实践中使用它? (案件存在,我知道。)

8 个答案:

答案 0 :(得分:217)

取自Sun的好tutorial

动机

使用静态编译的编程语言(如C和C ++)编写的应用程序将编译为本机特定于机器的指令并保存为可执行文件。将代码组合成可执行本机代码的过程称为链接 - 将单独编译的代码与共享库代码合并以创建可执行应用程序。这在动态编译的编程语言(例如Java)中是不同的。在Java中,Java编译器生成的.class文件保持原样,直到加载到Java虚拟机(JVM)中 - 换句话说,链接过程由JVM在运行时执行。类根据“需要”加载到JVM中。当一个加载的类依赖于另一个类时,那么该类也会加载。

当启动Java应用程序时,要运行的第一个类(或应用程序的入口点)是具有名为main()的public static void方法的类。该类通常具有对其他类的引用,并且所有加载引用类的尝试都由类加载器执行。

要了解这种递归类加载以及一般的类加载想法,请考虑以下简单类:

public class HelloApp {
   public static void main(String argv[]) {
      System.out.println("Aloha! Hello and Bye");
   }
}

如果您运行此类指定-verbose:class命令行选项,以便它打印正在加载的类,您将获得如下所示的输出。请注意,这只是一个部分输出,因为列表太长而无法显示在这里。

prmpt>java -verbose:class HelloApp



[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

如您所见,首先加载应用程序类(HelloApp)所需的Java运行时类。

Java 2平台中的类加载器

Java编程语言不断发展,使应用程序开发人员的日常生活更加轻松。这是通过提供简化生活的API来实现的,它允许您专注于业务逻辑而不是基本机制的实现细节。最近,J2SE 1.5更改为J2SE 5.0,以反映Java平台的成熟度,这一点很明显。

从JDK 1.2开始,内置于JVM中的引导类加载器负责加载Java运行时的类。此类加载器仅加载在引导类路径中找到的类,并且由于这些是受信任的类,因此不会对不受信任的类执行验证过程。除了引导类加载器之外,JVM还有一个扩展类加载器,负责从标准扩展API加载类,以及一个系统类加载器,它从一般类路径和应用程序类加载类。

由于存在多个类加载器,因此它们在树中表示,其根是引导类加载器。每个类加载器都有对其父类加载器的引用。当要求类加载器加载类时,它会在尝试加载项本身之前查询其父类加载器。父母反过来咨询其父母,依此类推。所以只有在所有祖先类加载器都找不到当前类加载器涉及的类之后。换句话说,使用委托模型。

java.lang.ClassLoader类

java.lang.ClassLoader是一个抽象类,可以由需要扩展JVM动态加载类的方式的应用程序进行子类化。 java.lang.ClassLoader(及其子类)中的构造函数允许您在实例化新的类加载器时指定父级。如果未明确指定父级,则将将虚拟机的系统类装入器指定为默认父级。换句话说,ClassLoader类使用委托模型来搜索类和资源。因此,ClassLoader的每个实例都有一个关联的父类加载器,因此在请求查找一个或多个类时,在尝试查找类或资源本身之前,该任务被委托给其父类加载器。 ClassLoader的loadClass()方法在调用加载类时按顺序执行以下任务:

如果已经加载了一个类,则返回它。 否则,它将搜索新类委托给父类加载器。 如果父类加载器未找到该类,loadClass()将调用方法findClass()来查找并加载该类。 如果父类加载器找不到类,finalClass()方法将在当前类加载器中搜索该类。


原始文章中还有更多内容,它还向您展示了如何实现自己的网络类加载器,它可以回答您关于原因(以及如何)的问题。另请参阅API docs

答案 1 :(得分:44)

大多数Java开发人员永远不需要显式使用类加载器(除了加载资源以便它们在JAR中捆绑时仍能正常工作),更不用说编写自己的了。

ClassLoader在大型系统和服务器应用程序中用于执行以下操作:

  • 模块化系统并在运行时加载,卸载和更新模块
  • 并行使用不同版本的API库(例如XML解析器)
  • 隔离在同一JVM中运行的不同应用程序(确保它们不会相互干扰,例如通过静态变量)

答案 2 :(得分:27)

  

问题是“为什么要打扰   这个ClassLoader类存在“?

嗯,大多数情况下,如果出错,你可以解决问题: - )。

确实如此,只要您编写一个应用程序,将其编译为JAR并且可能包含一些额外的库JAR,您就不需要了解类加载器,它只会起作用。

尽管如此,了解一下类加载器和类加载有助于更好地理解幕后发生的事情。例如,“静态初始化器”将在加载类时运行,因此要了解它们何时运行,您需要知道类加载器如何决定何时加载它们。

  

也..你在实践中如何使用它?

对于简单的情况,您不需要它们。但是,如果您需要在运行时动态加载代码并使用显式控制来源(例如,通过网络加载,加载编译时不可用的插件等),您可能需要执行更多操作。然后你可以,例如编写自己的类加载器。请参阅其他答案链接。

答案 3 :(得分:12)

Java中的

ClassLoader是一个用于在Java中加载类文件的类。 Java代码由javac编译器编译成类文件,JVM通过执行类文件中编写的字节代码来执行Java程序。

ClassLoader负责从文件系统,网络或任何其他来源加载类文件。 Java中使用了三个默认的类加载器, Bootstrap 扩展系统或应用程序类加载器。

ClassLoader

How ClassLoader works

## ClassLoader与JVM的交互 enter image description here

更多@:how-classloader-works-in-java.html

答案 4 :(得分:4)

类加载器是JVM的一个功能组件,它将类数据从“.class”文件或从网络加载到堆中的方法区域。

看起来像JVM的一个组成部分,但作为最终的java用户,我为什么要关注它?原因如下:

每个类加载器都有自己的名称空间,特定类加载器调用的类进入它的名称空间。

由两个不同的类加载器调用的类将无法相互查看,从而提高了安全性。

类加载器父子委托机制确保java api类永远不会被未经授权的代码攻击。

详情请见here

答案 5 :(得分:1)

类加载器是分层的。类被引入JVM,因为它们在已经在JVM中运行的类中由名称引用。

如何加载第一堂课?
第一个类是在您的类中声明的var axisHelper = new THREE.AxisHelper(200); axisHelper.position.z = 100; scene.add(axisHelper); 方法的帮助下加载的。所有后续加载的类都由已加载并运行的类加载。

类加载器创建命名空间。所有 JVM 都包含至少一个嵌入在JVM中的类加载器,称为原始(或引导程序)类加载器。这是一回事,我们将看看非原始类加载器。 JVM中有钩子,允许用户定义的类加载器代替原始类加载器。以下是JVM创建的类加载器。

Bootstrap(原始) 此类加载器无法重新加载。加载JDK内部类,java。*包(通常加载rt.jar和i18n.jar)。 Extesions 此类加载器无法重新加载。从JDK扩展目录(通常是JRE的lib / ext)加载jar文件。 系统 此类加载器无法重新加载。从系统类路径加载类。

https://stackoverflow.com/a/32549777/22417

答案 6 :(得分:1)

当您问为什么ClassLoader类存在时,原因很简单-它是负责在运行时查找和加载类文件的类。

让我们详细说明。

在JVM中,每个类均由java.lang.ClassLoader的某些实例加载。 每当您通过通常的Java程序启动java <classname>命令启动新的JVM时,第一步就是将所有关键类加载到正常工作所需的内存中,例如java.lang.Object和其他运行时类({{1} }。

现在,ClassLoader实际上包含三个部分:

  • rt.jar负责制作这些类 可用,即将这些类加载到内存中。

  • 下一个任务是将所有外部库/ JAR加载到 内存,以使应用程序正常工作。 BootstrapClassLoader是 负责这项任务。这个类加载器负责 加载java.ext.dirs路径中提到的所有.jar文件。

  • 第三个也是最重要的重要类加载器是ExtClassLoader。 应用程序类加载器负责类的加载 系统属性java.class.path中提到的文件。

还要注意,可以重写默认的ClassLoader实现,使您能够以有用和有趣的方式自定义JVM,从而完全重新定义将类文件引入系统的方式。

enter image description here

查看以了解有关Java Class Loader的更多信息。

答案 7 :(得分:0)

类加载器

ClassLoader 是 Java 运行时环境 (JRE) 的一部分,它动态将类(环境对象 - java.lang.Class 和文件 .class)加载到 JVM(Java虚拟机)。 JRE 使用延迟类加载(按需)它可以减少内存占用。当应用程序需要某个类 JRE 要求 ClassLoader 加载这个类

有一个ClassLoader类的层次结构

  • BootStrap 或 Primodial - root 并且是内置的(getClassLoader() 时返回 null)JDK 类。从 rt.jar 加载类
  • Extension(Platform Java v9) - 核心 Java 类。从 jre/lib/ext 目录加载类或由 java.ext.dirs 系统属性指向
  • 系统/应用程序 - 来自 classpath[About] 或命令行选项(-cp、-classpath)的应用程序类

此外,您还可以为您的特定情况创建自己的 ClassLoader 类。例如从某个存储库加载类,使用版本控制、卸载、安全

要检查究竟是谁加载了您的课程,请使用 getClassLoader()

SomeClass.class.getClassLoader()

寻找类流(委托模型)

child classloader find in cache 
    if not 
        parent classloader find in cache 
            if not
        parent classloader try to load
    if not
child classloader try to load

[ClassNotFoundException vs NoClassDefFoundError and Implicit vs Explicit class loading]

[iOS Dynamic Linker]