`
forxinyang
  • 浏览: 6053 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

java类加载器体系结构

    博客分类:
  • Java
 
阅读更多

 

java类加载器体系结构(含hotswap原理)

jvm classLoader architecture :

a, Bootstrap ClassLoader/启动类加载器
主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作.

b, Extension ClassLoader/扩展类加载器
主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作

c, System ClassLoader/系统类加载器
主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作.

b, User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)
在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性.

类加载器的特性:

1, 每个ClassLoader都维护了一份自己的名称空间, 同一个名称空间里不能出现两个同名的类。
2, 为了实现java安全沙箱模型顶层的类加载器安全机制, java默认采用了 ” 双亲委派的加载链 ” 结构.
如下图:
java class loader

Class Diagram:
classloader 类图

类图中, BootstrapClassLoader是一个单独的java类, 其实在这里, 不应该叫他是一个java类。
因为, 它已经完全不用java实现了。

它是在jvm启动时, 就被构造起来的, 负责java平台核心库。(具体上面已经有介绍)

启动类加载实现 (其实我们不用关心这块, 但是有兴趣的, 可以研究一下 ):
bootstrap classLoader 类加载原理探索

自定义类加载器加载一个类的步骤 :

自定义类加载器加载一个类的步骤

ClassLoader 类加载逻辑分析, 以下逻辑是除 BootstrapClassLoader 外的类加载器加载流程:

// 检查类是否已被装载过
Class c = findLoadedClass(name);
if (c == null ) {
     // 指定类未被装载过
     try {
         if (parent != null ) {
             // 如果父类加载器不为空, 则委派给父类加载
             c = parent.loadClass(name, false );
         } else {
             // 如果父类加载器为空, 则委派给启动类加载加载
             c = findBootstrapClass0(name);
         }
     } catch (ClassNotFoundException e) {
         // 启动类加载器或父类加载器抛出异常后, 当前类加载器将其
         // 捕获, 并通过findClass方法, 由自身加载
         c = findClass(name);
     }
}

用Class.forName加载类
Class.forName使用的是被调用者的类加载器来加载类的.
这种特性, 证明了java类加载器中的名称空间是唯一的, 不会相互干扰.
即在一般情况下, 保证同一个类中所关联的其他类都是由当前类的类加载器所加载的.

public static Class forName(String className)
     throws ClassNotFoundException {
     return forName0(className, true , ClassLoader.getCallerClassLoader());
}
 
/** Called after security checks have been made. */
private static native Class forName0(String name, boolean initialize,
ClassLoader loader)
     throws ClassNotFoundException;

上图中 ClassLoader.getCallerClassLoader 就是得到调用当前forName方法的类的类加载器

线程上下文类加载器
java默认的线程上下文类加载器是 系统类加载器(AppClassLoader).

// Now create the class loader to use to launch the application
try {
    loader = AppClassLoader.getAppClassLoader(extcl);
} catch (IOException e) {
    throw new InternalError(
"Could not create application class loader" );
}
 
// Also set the context class loader for the primordial thread.
Thread.currentThread().setContextClassLoader(loader);

以上代码摘自sun.misc.Launch的无参构造函数Launch()。
使用线程上下文类加载器, 可以在执行线程中, 抛弃双亲委派加载链模式, 使用线程上下文里的类加载器加载类.
典型的例子有, 通过线程上下文来加载第三方库jndi实现, 而不依赖于双亲委派.
大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。
还有一些采用 hotswap 特性的框架, 也使用了线程上下文类加载器, 比如 seasar (full stack framework in japenese).

线程上下文从根本解决了一般应用不能违背双亲委派模式的问题.
使java类加载体系显得更灵活.

随着多核时代的来临, 相信多线程开发将会越来越多地进入程序员的实际编码过程中. 因此,
在编写基础设施时, 通过使用线程上下文来加载类, 应该是一个很好的选择.

当然, 好东西都有利弊. 使用线程上下文加载类, 也要注意, 保证多根需要通信的线程间的类加载器应该是同一个,
防止因为不同的类加载器, 导致类型转换异常(ClassCastException).

自定义的类加载器实现
defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)
是java.lang.Classloader提供给开发人员, 用来自定义加载class的接口.

使用该接口, 可以动态的加载class文件.

例如,
在jdk中, URLClassLoader是配合findClass方法来使用defineClass, 可以从网络或硬盘上加载class.

而使用类加载接口, 并加上自己的实现逻辑, 还可以定制出更多的高级特性.

比如,

一个简单的hot swap 类加载器实现:

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
 
/**
* 可以重新载入同名类的类加载器实现
*
 
* 放弃了双亲委派的加载链模式.
* 需要外部维护重载后的类的成员变量状态.
*
* @author ken.wu
* @mail ken.wug@gmail.com
* 2007-9-28 下午01:37:43
*/
public class HotSwapClassLoader extends URLClassLoader {
 
    public HotSwapClassLoader(URL[] urls) {
        super (urls);
    }
 
    public HotSwapClassLoader(URL[] urls, ClassLoader parent) {
        super (urls, parent);
    }
 
    public Class load(String name)
          throws ClassNotFoundException {
        return load(name, false );
    }
 
    public Class load(String name, boolean resolve)
          throws ClassNotFoundException {
        if ( null != super .findLoadedClass(name))
            return reload(name, resolve);
 
        Class clazz = super .findClass(name);
 
        if (resolve)
            super .resolveClass(clazz);
 
        return clazz;
    }
 
    public Class reload(String name, boolean resolve)
          throws ClassNotFoundException {
        return new HotSwapClassLoader( super .getURLs(), super .getParent()).load(
            name, resolve);
    }
}
 
public class A {
    private B b;
 
    public void setB(B b) {
         this .b = b;
    }
 
    public B getB() {
         return b;
    }
}
 
public class B {}

这个类的作用是可以重新载入同名的类, 但是, 为了实现hotswap, 老的对象状态
需要通过其他方式拷贝到重载过的类生成的全新实例中来。(A类中的b实例)

而新实例所依赖的B类如果与老对象不是同一个类加载器加载的, 将会抛出类型转换异常(ClassCastException).

为了解决这种问题, HotSwapClassLoader自定义了load方法. 即当前类是由自身classLoader加载的, 而内部依赖的类还是老对象的classLoader加载的.public class TestHotSwap {

public static void main(String args[]) {
    A a = new A();
    B b = new B();
    a.setB(b);
 
    System.out.printf("A classLoader is %s n" , a.getClass().getClassLoader());
    System.out.printf("B classLoader is %s n" , b.getClass().getClassLoader());
    System.out.printf("A.b classLoader is %s n" ,   a.getB().getClass().getClassLoader());
 
    HotSwapClassLoader c1 = new HotSwapClassLoader( new URL[]{ new URL( "file:\e:\test\")} , a.getClass().getClassLoader());
    Class clazz = c1.load(" test.hotswap.A ");
    Object aInstance = clazz.newInstance();
 
    Method method1 = clazz.getMethod(" setB ", B.class);
    method1.invoke(aInstance, b);
 
    Method method2 = clazz.getMethod(" getB ", null);
    Object bInstance = method2.invoke(aInstance, null);
 
    System.out.printf(" reloaded A.b classLoader is %s n", bInstance.getClass().getClassLoader());
}
}
输出

A classLoader is sun.misc.Launcher$AppClassLoader@19821f
B classLoader is sun.misc.Launcher$AppClassLoader@19821f
A.b classLoader is sun.misc.Launcher$AppClassLoader@19821f
reloaded A.b classLoader is sun.misc.Launcher$AppClassLoader@19821f

转载请注明原文链接:http://kenwublog.com/structure-of-java-class-loader

分享到:
评论

相关推荐

    深入探讨 Java 类加载器

    Java 类加载器体系是一个树状结构,主要由以下几部分组成: - **引导类加载器(Bootstrap ClassLoader)**:加载JRE的核心类库,如rt.jar。 - **扩展类加载器(Extension ClassLoader)**:加载JRE的扩展库,位于jre...

    Java类加载器机制与模型.pdf

    类加载器之间形成了一种层次结构,称为**类加载器层次体系**,每个类加载器都有明确的职责范围,共同协作完成整个JVM的类加载工作。 类加载器机制对于理解和解决Java中的问题,如类冲突、安全控制以及插件系统设计...

    JAVA ClassLoader 讲解 (类加载器)

    Java的类加载器体系结构由三个主要类型的类加载器组成: 1. **引导类加载器(Bootstrap ClassLoader)**:这是最基础的类加载器,负责加载Java的核心库类,如`java.lang`包下的类。 2. **扩展类加载器(Extension ...

    jvm 加载class文件

    Java类加载器体系结构主要包括以下几种类型的加载器: 1. **启动类加载器(Bootstrap ClassLoader)**:负责加载Java的核心类库(位于JRE/lib/rt.jar等文件中),这是系统级别加载器,无法通过Java代码直接获取。 2...

    Java动态类加载机制研究及应用.pdf

    为了实现这个目标,需要对 Java 类加载器的体系结构、动态类加载机制原理、实现过程和实现方法进行分析。 Java 类加载器是 Java 虚拟机(JV M)的一部分,负责加载 Java 类文件并将其转换为可执行代码。 Java 类...

    Java类加载原理解析文档

    首先,我们来了解Java虚拟机(JVM)的类加载器结构。JVM预定义了三种主要的类加载器: 1. 启动(Bootstrap)类加载器:这是最基础的类加载器,由本地代码实现,负责加载`<Java_Runtime_Home>/lib`目录下的核心类库...

    Java类加载原理解析

    **Java虚拟机类加载器结构** Java 虚拟机预定义了三种类型的类加载器: 1. **启动(Bootstrap)类加载器**:这是最基础的类加载器,由本地代码实现,负责加载JDK安装目录下的<Java_Runtime_Home>/lib目录下的核心...

    Java类加载机制.pdf

    类加载机制涉及类加载顺序、类加载器的体系结构、类加载过程以及双亲委派模型等核心概念。架构师或高级开发人员必须深刻理解这些知识点,以便在进行大型互联网平台架构设计和开发时做出正确的决策。 首先,类加载指...

    java 体系结构图,不错的总结,复习的资料

    这个压缩包包含的“体系结构图”很可能是以图形形式展示了Java的核心概念,包括JVM(Java虚拟机)、类加载器、内存模型、线程管理、垃圾收集等重要方面。 首先,让我们从Java的基础开始。Java是一种面向对象的、跨...

    黑马程序员------类加载器学习注意点

    Java的类加载器体系采用的是双亲委派模型,这意味着当一个类加载器接收到加载类的请求时,它会首先将任务委托给父类加载器,只有当父类加载器无法找到该类时,子类加载器才会尝试自己加载。 其次,自定义类加载器是...

    Java体系结构介绍

    ### Java体系结构介绍 #### 一、Java 是什么 Java是一种高级编程语言,它具有开放性、跨平台性、安全性及面向对象等特性。Java语言的设计借鉴了C和C++等面向对象语言的经验,但在语法上更为简洁。它可以运行在多种...

    Java类加载机制在E-learning平台功能模块更新中的应用.pdf

    Java的类加载器体系结构由四个主要部分组成:BootstrapClassLoader、ExtensionClassLoader、ApplicationClassLoader和CustomClassLoader。BootstrapClassLoader是JVM的一部分,负责加载JRE核心类库,如位于JAVA_HOME...

    Java动态类加载机制应用研究.pdf

    文章《Java动态类加载机制应用研究.pdf》通过分析Java类加载器的层次体系结构和动态加载机制的原理,探讨了动态类加载技术在实际中的应用,并以高校网站管理平台的文件发布模块为例进行了具体说明。 首先,我们来看...

    Java安全体系结构1

    本文将深入探讨Java如何通过其语言特性、类加载器和安全管理器来实现安全性。 首先,Java的源代码被编译成字节码(class文件),这是Java平台无关性的关键。字节码是一种平台无关的中间表示,可以在任何支持Java...

    心得.rar心得.rar

    5. **Java类加载器体系结构**:深入解析Java的类加载过程,包括启动类加载器、扩展类加载器、系统类加载器和自定义类加载器的层次关系,以及双亲委托模型。 6. **Java偏向锁实现原理**:解释了偏向锁是如何减少无...

    classloader体系结构(含hotswap)

    Java的类加载器(ClassLoader)...总结来说,Java的类加载器体系结构是其动态性和灵活性的关键组成部分。通过理解这个体系,开发者能够更好地管理类的加载,实现代码的动态加载和替换,优化应用程序的性能和维护性。

    weblogic类加载过程简述

    WebLogic的类加载器体系遵循“父类加载器优先”原则,这意味着当一个类加载请求发生时,首先由父类加载器尝试加载,只有在其无法找到相应类时,才会将请求传递给子类加载器。WebLogic的主要类加载器包括Bootstrap类...

    Java虚拟机和Java程序的生命周期?

    - **扩展类加载器(Extension ClassLoader)**:这个类加载器继承自启动类加载器,用于加载扩展库中的类,这些类通常位于`JAVA_HOME/jre/lib/ext`目录下。 - **系统类加载器(System ClassLoader)**:也称为...

    1.JVM与Java体系结构

    JVM采用双亲委派模型进行类加载,当加载类时,会先查找父加载器,如果父加载器无法加载,则由当前加载器尝试加载。这种机制保证了类的唯一性,避免了类的冲突。 1.5 调优与问题排查 理解JVM的工作原理对于Java...

    基于沙箱的Java安全体系结构

    ### 基于沙箱的Java安全体系结构 #### 概述 Java作为一种跨平台的编程语言,其安全模型的设计尤为关键。Java的安全沙箱机制是确保Java应用程序能够在不损害系统安全的前提下运行的重要保障。本文将详细介绍Java...

Global site tag (gtag.js) - Google Analytics