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

java classLoader体系结构使用详解

阅读更多

原创整理不易,转载请注明出处:java classLoader体系结构使用详解

代码下载地址:http://www.zuidaima.com/share/1774052029516800.htm

jvm classLoader architecture:

  1. Bootstrap ClassLoader/启动类加载器 
    主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作。
  2. Extension ClassLoader/扩展类加载器 
    主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。
  3. System ClassLoader/系统类加载器 
    主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。
  4. User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类) 
    在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。

类加载器的特性:

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

classloader-architecture

classloader-class-diagram 

类图中, BootstrapClassLoader是一个单独的java类, 其实在这里, 不应该叫他是一个java类。因为,它已经完全不用java实现了。它是在jvm启动时, 就被构造起来的, 负责java平台核心库。

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

classloader-load-class

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);  
     }  
}  

线程上下文类加载器
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)。

为什么要使用这种双亲委托模式呢?

  1. 因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
  2. 考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的ClassLoader。

java动态载入class的两种方式:

  1. implicit隐式,即利用实例化才载入的特性来动态载入class
  2. explicit显式方式,又分两种方式:
    1. java.lang.Class的forName()方法
    2. java.lang.ClassLoader的loadClass()方法

用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方法的类的类加载器

static块在什么时候执行?

  • 当调用forName(String)载入class时执行,如果调用ClassLoader.loadClass并不会执行.forName(String,false,ClassLoader)时也不会执行.
  • 如果载入Class时没有执行static块则在第一次实例化时执行.比如new ,Class.newInstance()操作
  • static块仅执行一次

各个java类由哪些classLoader加载?

  • java类可以通过实例.getClass.getClassLoader()得知
  • 接口由AppClassLoader(System ClassLoader,可以由ClassLoader.getSystemClassLoader()获得实例)载入
  • ClassLoader类由bootstrap loader载入

NoClassDefFoundError和ClassNotFoundException

  • NoClassDefFoundError:当java源文件已编译成.class文件,但是ClassLoader在运行期间在其搜寻路径load某个类时,没有找到.class文件则报这个错
  • ClassNotFoundException:试图通过一个String变量来创建一个Class类时不成功则抛出这个异常
2
0
分享到:
评论

相关推荐

    JAVA ClassLoader 讲解 (类加载器)

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

    ClassLoader

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

    Java四大核心技术思想详解.doc

    Java类装载器体系结构设计灵活,支持不同类型的类装载器来适应不同的应用场景。主要分类包括: 1. **启动类装载器(Bootstrap Class Loader)**:它是JVM的一部分,负责加载Java核心库,如`rt.jar`。这些库通常位于...

    Tomcat研究之ClassLoader.pdf

    #### 二、Tomcat的ClassLoader体系结构 Tomcat采用了独特的类加载机制来处理不同的类库加载需求。其ClassLoader体系结构可以分为以下几个层次: 1. **Bootstrap ClassLoader**:这是JVM自带的类加载器,负责加载...

    Java核心知识体系:反射机制详解.pdf

    【Java反射机制详解】 Java反射机制是Java编程语言的核心特性之一,它允许程序在运行时检查和操作类、接口、对象等的内部结构。反射在Java中扮演着至关重要的角色,尤其是在开发框架、动态代理、元数据处理以及高度...

    java面试题题库详解

    ### Java面试题题库详解 #### 1. Java基本概念:String是什么?它与其它类型有何不同? **知识点概述:** - **String 类型的基本理解:** 在 Java 中,`String` 是一个不可变的对象,它代表了字符序列。 - **与...

    Java加载。jar包

    ### Java加载.jar包详解 #### 一、Java 类加载机制概览 自 JDK 1.2 版本之后,Java 类加载机制发生了一个重要的变化,引入了一种名为**类加载委托**的概念。这一机制的核心思想在于,如果某个 `ClassLoader` 无法...

    Java常见的面试试题及详解.txt

    Java中的异常体系结构是怎样的? - Throwable:所有错误和异常的父类。 - Error:程序无法处理的情况,如堆栈溢出等。 - Exception:程序本身可以处理的异常。 - RuntimeException:运行时异常,如空指针异常。 -...

    Java 培训教程(千峰教育)

    Java的体系结构中立性和可移植性保证了它可以在多种平台上运行,而解释型和高性能则满足了不同场景下的需求。多线程的支持更是增强了Java在并发编程方面的能力。通过对这些核心概念的理解,可以帮助开发者更好地掌握...

    java基础面试题目大全, 合适JAVA面试的程序员

    Java基础面试题目主要涵盖了许多核心概念,包括语言特性、...以上是Java基础面试题目的核心知识点详解,涵盖了Java语言、集合框架、多线程、异常处理、面向对象、Web开发等多个方面,是Java程序员面试必备的知识体系。

    java 并发编程、java虚拟机学习

    JVM内部结构详解 - **类加载器子系统**:由启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用类加载器(Applications ClassLoader)组成。 - **内存区域**: - **方法区**:存放类的...

    JVM详解-淘宝内部资料

    "JVM详解-淘宝内部资料"提供了一套深入理解JVM的资源,涵盖了从基础到高级的各种主题,包括Java虚拟机的生命周期、JVM的体系结构、各个组件的详细解析以及垃圾收集(Garbage Collection, GC)机制等内容。...

    spring framework体系结构及模块jar依赖关系详解

    Spring Framework 体系结构及模块 JAR 依赖关系详解 Spring Framework 是一个广泛使用的 Java 企业级应用程序开发框架,提供了一个完整的生态系统来构建企业级应用程序。 Spring Framework 由多个模块组成,每个...

    深入JVM整理文档

    #### 1.1、Java体系结构的四个方面 Java体系结构主要包括以下几个方面: 1. **Java程序设计语言**:这是编写Java程序的基础,包含语法、关键字、语句等元素。 2. **Java class文件格式**:这是一种标准的文件格式...

    Java基础教程.md.pdf

    ### Java基础教程知识点详解 #### 1. Java简介 ##### 1.1 认识Java - **诞生时间**:1995年5月23日,Java语言由Sun Microsystems公司推出。 - **创始人**:James Gosling,通常被称为“Java之父”。 ##### 1.2 ...

    jvm的基本原理及结构

    2. **类加载机制**:JVM使用类加载器(ClassLoader)将.class文件加载到内存中,类加载器体系结构包括Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader,它们分别负责加载不同的类库。...

Global site tag (gtag.js) - Google Analytics