什么是Java ClassLoader?
在一些简单的句子中,什么是Java ClassLoader,什么时候使用,为什么?
好的,我读了一篇wiki文章。 ClassLoader加载类。 好。 所以如果我包含jar文件并导入,一个ClassLoader可以完成这个工作。
我为什么要打扰这个ClassLoader? 我从来没有用过它,不知道它存在。
问题是,为什么ClassLoader类存在? 而且,你如何在实践中使用它? (我知道有这种情况。)
从这个来自Sun的好教程 :
动机
以静态编译的编程语言(例如C和C ++)编写的应用程序被编译为本机,特定于机器的指令并保存为可执行文件。 将代码组合成可执行本地代码的过程称为链接 – 将单独编译的代码与共享库代码合并以创build可执行应用程序。 这在dynamic编译的编程语言(如Java)中是不同的。 在Java中,Java编译器生成的.class文件保持不变,直到加载到Java虚拟机(JVM) – 换句话说,链接过程由JVM在运行时执行。 根据需要将类加载到JVM中。 而当一个被加载的类依赖于另一个类,那么该类也被加载。
当Java应用程序启动时,运行的第一个类(或者进入应用程序的入口点)是一个带有public static void method(名为main())的类。 这个类通常具有对其他类的引用,并且所有加载引用类的尝试都由类加载器执行。
为了得到这种recursion类加载的感觉以及一般的类加载思想,请考虑以下简单的类:
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来完成的,让您专注于业务逻辑而不是基本机制的实现细节。 为了反映Java平台的成熟度,最近J2SE 1.5到J2SE 5.0的变化就certificate了这一点。
从JDK 1.2开始,JVM中内置的引导类加载器负责加载Java运行时的类。 这个类加载器只加载在启动类path中find的类,因为这些是可信类,所以validation过程不像不可信类一样执行。 除了引导类加载器之外,JVM还有一个扩展类加载器负责从标准扩展API加载类,还有一个系统类加载器从一般类path以及应用程序类加载类。
由于有多个类加载器,所以它们被表示在一个以引导类加载器为根的树中。 每个类加载器都有一个对其父类加载器的引用。 当一个类加载器被要求加载一个类时,它会在尝试加载这个项目之前先咨询它的父类加载器。 父母轮stream咨询父母,等等。 所以只有在所有的祖先类加载器都找不到当前的类加载器所涉及的类。 换句话说,使用委托模式。
java.lang.ClassLoader类
java.lang.ClassLoader
是一个抽象类,可以由需要扩展JVMdynamic加载类的方式的应用程序进行子类化。 java.lang.ClassLoader
(及其子类)中的构造函数允许您在实例化新的类加载器时指定父级。 如果您没有明确指定父级,则虚拟机的系统类加载器将被指定为默认父级。 换句话说,ClassLoader类使用委托模型来search类和资源。 因此,ClassLoader的每个实例都有一个关联的父类加载器,所以在请求查找一个或多个资源时,在尝试查找类或资源本身之前,将该任务委托给其父类加载器。 ClassLoader的loadClass()
方法执行以下任务,以便在调用时加载类:
如果一个类已经被加载,它将返回它。 否则,它会将新类的search委托给父类加载器。 如果父类加载器没有find该类,则loadClass()
调用方法findClass()
来查找并加载该类。 如果父类加载器未find该类,则finalClass()
方法在当前类加载器中search该类。
在原始文章中还有更多的内容,它也向你展示了如何实现自己的networking类加载器,它解答了你为什么(以及如何)的问题。 另请参阅API文档 。
大多数Java开发人员永远不需要明确地使用类加载器(除了加载资源,以便它们在JAR中捆绑时仍能工作),更不用说写自己的代码了。
ClassLoaders在大型系统和服务器应用程序中用于执行如下操作:
- 模块化系统并在运行时加载,卸载和更新模块
- 并行使用不同版本的API库(例如XMLparsing器)
- 隔离在同一个JVM中运行的不同应用程序(确保它们不会相互干扰,例如通过静态variables)
问题是“为什么要打扰这个ClassLoader类存在”?
那么,大多数情况下,如果出现问题,你可以修复:-)。
确实如此,只要你编写一个应用程序,把它编译成一个JAR文件,也许还包括一些额外的库JAR文件,你不需要知道类加载器,它就可以工作。
尽pipe如此,了解一些关于类加载器和类加载,以更好地理解幕后发生的事情是有帮助的。 作为一个例子,当一个类被加载时,“静态初始化器”将运行,所以为了理解它们何时运行,你需要知道类加载器如何决定何时加载它们。
另外..你怎么在实践中使用它?
对于简单的情况,你不需要它们。 但是,如果您需要在运行时dynamic加载代码,并在其中显式控制(例如通过networking加载,加载在编译时不可用的插件等),则可能需要做更多的事情。 然后你可以写你自己的类加载器。 查看其他答案的链接。
类加载器是JVM的一个function组件,它从“.class”文件或者通过networking加载Heap中的方法区域的类数据。
看起来像JVM的一个组成部分,但作为最终的Java用户,为什么我应该关心? 这是为什么:
每个类加载器都有它自己的名字空间,并且由特定的类加载器调用的类进入它的名字空间。
由两个不同的类加载器调用的类彼此不可见,从而增强了安全性。
类加载器父子代理机制确保java api类永远不会被未经授权的代码破解。
详情请看这里
Java中的ClassLoader
是一个用于在Java中加载类文件的类。 Java代码被javac
编译器编译成类文件,JVM通过执行写在类文件中的字节代码执行Java程序。
ClassLoader负责从文件系统,networking或任何其他来源加载类文件。 在Java, Bootstrap , Extension和System或Application class loader中有三个默认的类加载器。
## ClassLoader与JVM的交互
更多@: how-classloader-works-in-java.html
类加载器是分层的。 类被引入到JVM中,因为它们在已经在JVM中运行的类中被名称引用。
第一类怎么装?
第一个类是在你的类中声明的static main()
方法的帮助下加载的。 所有随后加载的类都由已加载并正在运行的类加载。
类加载器创build一个名称空间。 所有JVM都至less包含一个embeddedJVM中的类加载器,该JVM称为原始(或引导)类加载器。 这是一回事,我们将看看非原生类装载机。 JVM有钩子来允许用户定义的类加载器来代替原始类加载器。 这里是由JVM创build的类加载器。
Bootstrap(原始的)这个类加载器不可重载。 加载JDK内部类,java。*包(通常加载rt.jar和i18n.jar)。 Extesions这个类加载器不可重载。 从JDK扩展目录加载jar文件(通常是JRE的lib / ext)。 系统这个类加载器不可重载。 从系统类path加载类。