在几个简单的句子中,什么是Java ClassLoader,何时使用以及为什么?
好的,我读了一篇wiki文章.ClassLoader加载类.好.因此,如果我包含jar文件并导入,则ClassLoader可以完成这项工作.
我为什么要打扰这个ClassLoader?我从未使用它,也不知道它存在.
问题是,为什么ClassLoader类存在?而且,你如何在实践中使用它?(案件存在,我知道.)
摘自Sun的这篇精彩教程:
使用静态编译的编程语言(如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编程语言不断发展,使应用程序开发人员的日常生活变得更加轻松.这是通过提供简化生活的API来实现的,它允许您专注于业务逻辑而不是基本机制的实现细节.最近,J2SE 1.5更改为J2SE 5.0,以反映Java平台的成熟度.
从JDK 1.2开始,内置于JVM中的引导类加载器负责加载Java运行时的类.此类加载器仅加载在引导类路径中找到的类,并且由于这些类是受信任的类,因此不会对不受信任的类执行验证过程.除了引导类加载器之外,JVM还有一个扩展类加载器,负责从标准扩展API加载类,以及一个系统类加载器,它从一般类路径和应用程序类加载类.
由于存在多个类加载器,因此它们在树中表示,其根是引导类加载器.每个类加载器都有对其父类加载器的引用.当要求类加载器加载类时,它会在尝试加载项本身之前查询其父类加载器.父母反过来咨询其父母,依此类推.所以只有在所有祖先类加载器都找不到当前类加载器涉及的类之后.换句话说,使用委托模型.
这java.lang.ClassLoader
是一个抽象类,可以由需要扩展JVM动态加载类的方式的应用程序进行子类化.java.lang.ClassLoader
(和它的子类)中的构造函数允许您在实例化新的类加载器时指定父类.如果未明确指定父级,则将将虚拟机的系统类装入器指定为默认父级.换句话说,ClassLoader类使用委托模型来搜索类和资源.因此,ClassLoader的每个实例都有一个关联的父类加载器,因此在请求查找一个或多个类时,在尝试查找类或资源本身之前,该任务被委托给其父类加载器.loadClass()
当调用加载类时,ClassLoader 的方法按顺序执行以下任务:
如果已经加载了一个类,则返回它.否则,它将搜索新类委托给父类加载器.如果父类加载器未找到该类,则loadClass()
调用该方法findClass()
以查找并加载该类.finalClass()
如果父类加载器找不到类,则该方法在当前类加载器中搜索该类.
原始文章中还有更多内容,它还向您展示了如何实现自己的网络类加载器,它可以回答您关于原因(以及如何)的问题.另请参阅API文档.
大多数Java开发人员永远不需要显式使用类加载器(除了加载资源以便它们在JAR中捆绑时仍然有效),更不用说编写自己的了.
ClassLoaders在大型系统和服务器应用程序中用于执行以下操作:
模块化系统并在运行时加载,卸载和更新模块
并行使用不同版本的API库(例如XML解析器)
隔离在同一JVM中运行的不同应用程序(确保它们不会相互干扰,例如通过静态变量)
问题是"为什么要打扰这个ClassLoader类"?
好吧,大多数情况下,如果他们出错,你可以解决问题:-).
这是真的,只要您编写一个应用程序,将其编译为JAR并且可能包含一些额外的库JAR,您就不需要了解类加载器,它只会起作用.
尽管如此,了解类加载器和类加载有助于更好地理解幕后发生的事情.例如,"静态初始化器"将在加载类时运行,因此要了解它们何时运行,您需要知道类加载器如何决定何时加载它们.
还有..你怎么在实践中使用它?
对于简单的情况,您不需要它们.但是,如果您需要在运行时动态加载代码并使用显式控件(例如,通过网络加载,加载编译时不可用的插件等),您可能需要执行更多操作.然后你可以编写自己的类加载器.请参阅其他答案的链接.
ClassLoader
Java中的类是用于在Java中加载类文件的类.Java代码由javac
编译器编译成类文件,JVM通过执行类文件中编写的字节代码执行Java程序.
ClassLoader负责从文件系统,网络或任何其他来源加载类文件.Java,Bootstrap,Extension和System或Application类加载器中使用了三个默认的类加载器.
## ClassLoader与JVM的交互
更多@:how-classloader-works-in-java.html