什么是Java ClassLoader?


174

简单地说,什么是Java ClassLoader?何时使用Java?为什么?

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

我为什么要打扰这个ClassLoader?我从未使用过它,也不知道它的存在。

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


如果你缩小你的问题,例如,通过指点你不明白的特定部分,它与其他一些语言,你所熟悉的,等你会得到更好的结果
JRL

75
从某人寻找一些简单的句子来解释这个概念的角度来看,这是一个完全合理的问题
oxbow_lakes 2010年

该视频可能会引起
asmaier 2013年

Answers:


231

摘自Sun的这个不错的教程

动机

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

启动Java应用程序时,要运行的第一个类(或应用程序的入口点)是带有公共静态void方法(称为main())的类。此类通常具有对其他类的引用,并且所有加载引用的类的尝试均由类加载器执行。

为了大致了解这种递归类加载以及类加载的思想,请考虑以下简单类:

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来完成的,该API通过允许您专注于业务逻辑而不是基本机制的实现细节来简化您的生活。为了反映Java平台的成熟,最近将J2SE 1.5更改为J2SE 5.0可以证明这一点。

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

由于有多个类加载器,因此它们在树中表示,该树的根是引导类加载器。每个类加载器都有对其父类加载器的引用。当要求类加载器加载类时,它会在尝试加载项目本身之前先咨询其父类加载器。父级依次咨询其父级,依此类推。因此,只有在所有祖先类加载器都找不到该类后,当前类加载器才会参与。换句话说,使用了委托模型。

java.lang.ClassLoader类

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

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


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


47

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

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

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

29

问题是“为什么要麻烦这个ClassLoader类存在”?

好吧,主要是这样,如果它们出错了,您就可以修复它:-)。

没错,只要编写应用程序,将其编译为JAR并可能包括一些额外的库JAR,就无需了解类加载器,它就可以工作。

尽管如此,了解一些类加载器和类加载还是有帮助的,以便更好地了解幕后情况。例如,“静态初始化器”将在加载类时运行,因此要了解它们何时运行,您需要知道类加载器如何决定何时加载它们。

还..您如何在实践中使用它?

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


14

ClassLoaderJava中的class是用于加载Java中的类文件的类。编译javac器将Java代码编译到类文件中,然后JVM通过执行写入类文件中的字节码来执行Java程序。

ClassLoader负责从文件系统,网络或任何其他来源加载类文件。Java中使用了三种默认的类加载器,即BootstrapExtensionSystem或Application类加载器。

类加载器


ClassLoader如何工作

## ClassLoader与JVM的交互 在此处输入图片说明

更多@ cn.pngtree.com


6

类加载器是JVM的功能组件,可从“ .class”文件或通过网络将类数据加载到Heap的“方法区域”中。

看起来像是JVM不可或缺的一部分,但是作为最终的Java用户,我为什么要关注呢?原因如下:

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

由两个不同的类加载器调用的类将不会相互可见,从而增强了安全性。

类加载器的父子委派机制确保Java api类永远不会被未经授权的代码入侵。

详情请看这里


1

类加载器是分层的。在JVM中已运行的类中,通过名称对类进行了引用,从而将类引入到JVM中。

头等舱如何装车?
第一个类static main()在类中声明的方法的帮助下加载。所有随后加载的类均由已加载并正在运行的类加载。

类加载器创建一个名称空间。所有JVM至少包括一个嵌入在JVM内的类加载器,称为原始(或引导)类加载器。那是一回事,我们将研究非原始类加载器。JVM中具有挂钩,以允许使用用户定义的类加载器代替原始类加载器。这是由JVM创建的类加载器。

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

http://www.sbalasani.com/2015/01/java-class-loaders.html


1

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

让我们详细说明一下。

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

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

  • BootstrapClassLoader负责使这些类可用,即将这些类加载到内存中。

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

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

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

在此处输入图片说明

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.