`

classloader 文章集錦2

阅读更多

一 、ClassLoader

 
1,   什么是 ClassLoader?
    Java 程序并不是一个可执行文件,是需要的时候,才把装载到 JVM中。ClassLoader 做的工作就是 JVM 中将类装入内存。 而且,Java ClassLoader 就是用 Java 语言编写的。这意味着您可以创建自己的 ClassLoader
    ClassLoader 的基本目标是对类的请求提供服务。当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 试图返回一个表示这个类的 Class 对象。 通过覆盖对应于这个过程不同阶段的方法,可以创建定制的 ClassLoader。
2, 一些重要的方法
A)  方法 loadClass
        ClassLoader.loadClass() 是 ClassLoader 的入口点。该方法的定义如下:
        Class loadClass( String name, boolean resolve );
         name  JVM 需要的类的名称,如 Foo 或 java.lang.Object。
         resolve 参数告诉方法是否需要解析类。在准备执行类之前,应考虑类解析。并不总是需要解析。如果 JVM 只需要知道该类是否存在或找出该类的超类,那么就不需要解析。
    
    B)  方法 defineClass
       defineClass 方法是 ClassLoader 的主要诀窍。该方法接受由原始字节组成的数组并把它转换成 Class 对象。原始数组包含如从文件系统或网络装入的数据。defineClass 管理 JVM 的许多复杂、神秘和倚赖于实现的方面 -- 它把字节码分析成运行时数据结构、校验有效性等等。不必担心,您无需亲自编写它。事实上,即使您想要这么做也不能覆盖它,因为它已被标记成final的。

    C)  方法 findSystemClass
       findSystemClass 方法从本地文件系统装入文件。它在本地文件系统中寻找类文件,如果存在,就使用 defineClass 将原始字节转换成 Class 对象,以将该文件转换成类。当运行 Java 应用程序时,这是 JVM 正常装入类的缺省机制。(Java 2 中 ClassLoader 的变动提供了关于 Java 版本 1.2 这个过程变动的详细信息。) 对于定制的 ClassLoader,只有在尝试其它方法装入类之后,再使用 findSystemClass。原因很简单:ClassLoader 是负责执行装入类的特殊步骤,不是负责所有类。例如,即使 ClassLoader 从远程的 Web 站点装入了某些类,仍然需要在本地机器上装入大量的基本 Java 库。而这些类不是我们所关心的,所以要 JVM 以缺省方式装入它们:从本地文件系统。这就是 findSystemClass 的用途。

     D) 方法 resolveClass
   正如前面所提到的,可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的 loadClass 时,可以调用 resolveClass,这取决于 loadClass 的 resolve 参数的值。


   E) 方法 findLoadedClass
      findLoadedClass 充当一个缓存:当请求 loadClass 装入类时,它调用该方法来查看 ClassLoader 是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。应首先调用该方法。

3, 怎么组装这些方法
  1) 调用 findLoadedClass 来查看是否存在已装入的类。
  2) 如果没有,那么采用那种特殊的神奇方式来获取原始字节。
  3) 如果已有原始字节,调用 defineClass 将它们转换成 Class 对象。
  4) 如果没有原始字节,然后调用 findSystemClass 查看是否从本地文件系统获取类。
  5) 如果 resolve 参数是 true,那么调用 resolveClass 解析 Class 对象。
  6) 如果还没有类,返回 ClassNotFoundException。

4,Java 2 中 ClassLoader 的变动
1)loadClass 的缺省实现
   定制编写的 loadClass 方法一般尝试几种方式来装入所请求的类,如果您编写许多类,会发现一次次地在相同的、很复杂的方法上编写变量。 在 Java 1.2 中 loadClass 的实现嵌入了大多数查找类的一般方法,并使您通过覆盖 findClass 方法来定制它,在适当的时候 findClass 会调用 loadClass。 这种方式的好处是您可能不一定要覆盖 loadClass;只要覆盖 findClass 就行了,这减少了工作量。

2)新方法:findClass
     loadClass 的缺省实现调用这个新方法。findClass 的用途包含您的 ClassLoader 的所有特殊代码,而无需要复制其它代码(例如,当专门的方法失败时,调用系统 ClassLoader)。

3) 新方法:getSystemClassLoader
     如果覆盖 findClass 或 loadClass,getSystemClassLoader 使您能以实际 ClassLoader 对象来访问系统 ClassLoader(而不是固定的从 findSystemClass 调用它)。
 
4) 新方法:getParent 
    为了将类请求委托给父代 ClassLoader,这个新方法允许 ClassLoader 获取它的父代 ClassLoader。当使用特殊方法,定制的 ClassLoader 不能找到类时,可以使用这种方法。
父代 ClassLoader 被定义成创建该 ClassLoader 所包含代码的对象的 ClassLoader。

 

二。Java ClassLoader

Java ClassLoader
 

这是一篇较早时候写的文章,最近在J道看到一个与classloader有关的讨论,于是重新翻出来。

静态库、动态连接库

程序编制一般需经编辑、编译、连接、加载和运行几个步骤。在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”文件;在连接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中。这种库称为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。

为了克服这个缺点可以采用动态连接库。这个时候连接器仅仅是在可执行文件中打上标志,说明需要使用哪些动态连接库;当运行程序时,加载器根据这些标志把所需的动态连接库加载到内存。

另外在当前的编程环境中,一般都提供方法让程序在运行的时候把某个特定的动态连接库加载并运行,也可以将其卸载(例如Win32的LoadLibrary()&FreeLibrary()和Posix的dlopen()&dlclose())。这个功能被广泛地用于在程序运行时刻更新某些功能模块或者是程序外观。

What is ClassLoader?

与普通程序不同的是,Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。

JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,Bootstrap ClassLoader是用本地代码实现的,它负责加载核心Java Class(即所有java.*开头的类)。另外JVM还会提供两个ClassLoader,它们都是用Java语言编写的,由Bootstrap ClassLoader加载;其中Extension ClassLoader负责加载扩展的Java class(例如所有javax.*开头的类和存放在JRE的ext目录下的类),Application ClassLoader负责加载应用程序自身的类。

When to load the class?

什么时候JVM会使用ClassLoader加载一个类呢?当你使用java去执行一个类,JVM使用Application ClassLoader加载这个类;然后如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类A的ClassLoader,并用这个ClassLoader来加载类B。

Why use your own ClassLoader?

似乎JVM自身的ClassLoader已经足够了,为什么我们还需要创建自己的ClassLoader呢?

因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写你自己的ClassLoader,你可以做到:
1)在执行非置信代码之前,自动验证数字签名
2)动态地创建符合用户特定需要的定制化构建类
3)从特定的场所取得java class,例如数据库中
4) 等等

事实上当使用Applet的时候,就用到了特定的ClassLoader,因为这时需要从网络上加载java class,并且要检查相关的安全信息。

目前的应用服务器大都使用了ClassLoader技术,即使你不需要创建自己的ClassLoader,了解其原理也有助于更好地部署自己的应用。 

ClassLoader Tree & Delegation Model

当你决定创建你自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个ClassLoader对象时,需要指定一个父对象;如果没有指定的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。如下图:

在Java 1.2后,java class的加载采用所谓的委托模式(Delegation Modle),当调用一个ClassLoader.loadClass()加载一个类的时候,将遵循以下的步骤:
1)检查这个类是否已经被加载进来了?
2)如果还没有加载,调用父对象加载该类
3)如果父对象无法加载,调用本对象的findClass()取得这个类。

所以当创建自己的Class Loader时,只需要重载findClass()这个方法。

Unloading? Reloading?

当一个java class被加载到JVM之后,它有没有可能被卸载呢?我们知道Win32有FreeLibrary()函数,Posix有dlclose()函数可以被调用来卸载指定的动态连接库,但是Java并没有提供一个UnloadClass()的方法来卸载指定的类。

在Java中,java class的卸载仅仅是一种对系统的优化,有助于减少应用对内存的占用。既然是一种优化方法,那么就完全是JVM自行决定如何实现,对Java开发人员来说是完全透明的。

在什么时候一个java class/interface会被卸载呢?Sun公司的原话是这么说的:"class or interface may be unloaded if and only if its class loader is unreachable. Classes loaded by the bootstrap loader may not be unloaded."

事实上我们关心的不是如何卸载类的,我们关心的是如何更新已经被加载了的类从而更新应用的功能。JSP则是一个非常典型的例子,如果一个JSP文件被更改了,应用服务器则需要把更改后的JSP重新编译,然后加载新生成的类来响应后继的请求。

其实一个已经加载的类是无法被更新的,如果你试图用同一个ClassLoader再次加载同一个类,就会得到异常(java.lang.LinkageError: duplicate class definition),我们只能够重新创建一个新的ClassLoader实例来再次加载新类。至于原来已经加载的类,开发人员不必去管它,因为它可能还有实例正在被使用,只要相关的实例都被内存回收了,那么JVM就会在适当的时候把不会再使用的类卸载。

分享到:
评论

相关推荐

    classloader

    4. 考虑Java 2版本的兼容性:学习如何修改你的ClassLoader以适应Java 2及以上版本的特性,比如支持Service Provider Interface (SPI)。 在深入学习之前,你需要理解类的生命周期,以及类加载、链接和初始化的概念。...

    Java ClassLoader定制实例

    本篇文章将深入探讨Java ClassLoader的内部工作,并通过一个具体的实例来展示如何定制自己的ClassLoader。 首先,我们来看ClassLoader的基本工作流程。当JVM启动时,它会有一个初始的Bootstrap ClassLoader,用于...

    ClassLoader

    ### Java虚拟机中ClassLoader概述与双亲委托机制详解 #### 一、ClassLoader概念与作用 在Java编程语言中,`ClassLoader`是一个非常重要的组件,它负责加载程序运行所需的类文件到Java虚拟机(JVM)中。`ClassLoader`...

    ClassLoader运行机制 自己写的

    2. Extension ClassLoader:加载JDK扩展目录(如$JAVA_HOME/jre/lib/ext)中的类。 3. System ClassLoader(也称为AppClassLoader):加载`CLASSPATH`环境变量指定的类,以及应用主类路径(class path)上的类。 4. ...

    自定义classloader的使用

    在Java中,Classloader是加载类的关键组件,它负责查找、加载和初始化字节码文件。自定义Classloader允许开发者根据特定需求定制类的加载逻辑,例如加密类文件、隔离不同版本的库或者动态加载代码。本文将深入探讨...

    ClassLoader小例子

    2. **双亲委派模型** 这是一种为了防止类的重复加载和保证类加载的安全性而设计的机制。类加载请求会逐级向上委托,直到找到对应的类或者返回给最初发起请求的类加载器。 3. **ClassLoader的工作流程** - 加载:...

    深入理解ClassLoader工作机制.docx

    2. **验证**:验证是确保加载的类符合Java语言规范,不会破坏JVM的安全性。它检查字节码的格式、数据流和操作符计算、类和字段的访问控制等。 3. **准备**:在准备阶段,JVM为类的静态变量分配内存,并将其初始化为...

    java ClassLoader机制及其在OSGi中的应用

    2. OSGi的ClassLoader支持动态加载和卸载bundle,当bundle被激活或停用时,对应的类加载器可以按需加载或释放类,提高了系统的灵活性和可维护性。 3. OSGi的ClassLoader还支持类的重用,如果两个bundle引用了相同的...

    JVM ClassLoader简析

    首先,ClassLoader可以分为三种基本类型:Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader。Bootstrap ClassLoader是JVM启动时的第一个ClassLoader,负责加载JDK的`<JAVA_HOME>\lib`目录下...

    ClassLoader 详解.doc

    2. Extension ClassLoader:扩展类加载器。其主要任务是加载JRE的扩展目录下的JAR包,如JAVA_HOME/jre/lib/ext目录或由java.ext.dirs系统属性指定的路径。这种方式允许开发者添加JVM扩展功能,而无需修改核心类库。...

    java classloader

    `附录A.Java 2 SDK版原始码概观.pdf`可能提供了Java 2 SDK源码的概述,这对于理解ClassLoader的工作方式非常有帮助,因为你可以看到其内部的实现细节。 `CH_00-导读.pdf`则可能是整个系列的引导章节,介绍了接下来...

    ClassLoader 案例

    2. 对`loadClass()` 和 `findClass()` 的覆写,实现自定义加载逻辑。 3. 文件I/O操作,读取并加载指定目录下的.class文件。 4. 使用`Class.forName()` 或 `Class.getDeclaredMethods()`等反射API来动态调用加载的类...

    理解Java ClassLoader机制

    2. **加载类**:找到`.class`文件后,ClassLoader将其读入内存,并创建一个Class对象。这个过程可能涉及字节码验证,确保类的安全性。 3. **链接**:链接阶段包括三个子步骤:验证、准备和解析。验证确保字节码符合...

    ClassLoader的 一些测试

    2. Extension ClassLoader:扩展类加载器,负责加载JRE的扩展目录(jre/lib/ext目录下的jar文件)。 3. AppClassLoade:应用程序类加载器,也叫系统类加载器,负责加载用户类路径(classpath)上的类。 在Java中,...

    ClassLoader类加载机制和原理详解

    2. 类加载过程 类加载的过程通常分为三个阶段:加载、验证和准备、解析和初始化。 - 加载:查找并加载类的二进制数据。数据可能来自JAR文件、网络或自定义的加载源。 - 验证:确保类文件的字节码符合Java语法规则,...

    破解java加密的ClassLoader.java,在classloader植入破解代码

    破解java加密的ClassLoader.java,在classloader植入破解代码

    ClassLoader原理

    2. **Extension ClassLoader**:扩展类加载器,负责加载`<JAVA_HOME>\lib\ext`目录中的类库,或者是由`java.ext.dirs`系统变量所指定的目录下的类库。 3. **Application ClassLoader**:应用程序类加载器,也称为...

Global site tag (gtag.js) - Google Analytics