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

java classLoader 体系结构

 
阅读更多

原文出处:http://blog.chenlb.com/2009/06/java-classloader-architecture.html

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-architecture

classloader-class-diagram

classloader-class-diagram

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

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

classloader-load-class

classloader-load-class

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

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

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

 
  1. // Now create the class loader to use to launch the application  
  2. try {  
  3.     loader = AppClassLoader.getAppClassLoader(extcl);  
  4. catch (IOException e) {  
  5.     throw new InternalError(  
  6. "Could not create application class loader" );  
  7. }   
  8.   
  9. // Also set the context class loader for the primordial thread.  
  10. 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类加载器中的名称空间是唯一的, 不会相互干扰。
即在一般情况下, 保证同一个类中所关联的其他类都是由当前类的类加载器所加载的。

 
  1. public static Class forName(String className)  
  2.      throws ClassNotFoundException {  
  3.      return forName0(className, true , ClassLoader.getCallerClassLoader());  
  4. }   
  5.   
  6. /** Called after security checks have been made. */  
  7. private static native Class forName0(String name, boolean initialize,  
  8. ClassLoader loader)  
  9.      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类时不成功则抛出这个异常
分享到:
评论

相关推荐

    classloader体系结构(含hotswap)

    Java的类加载器(ClassLoader)体系结构是JVM(Java虚拟机)中至关重要的一部分,它负责将类的字节码转换为运行时的类实例。本文将深入探讨启动类加载器、扩展类加载器、系统类加载器以及用户自定义类加载器,同时还...

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

    二、ClassLoader的体系结构 ClassLoader形成一个树状结构,BootstrapClassLoader是根节点,ExtensionClassLoader是其子节点,SystemClassLoader是ExtensionClassLoader的子节点。用户还可以自定义ClassLoader,插入...

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

    Java 体系结构图是理解Java编程语言及其生态系统的关键工具,尤其对于初学者而言,它能够清晰地展现Java的各个组成部分以及它们之间的关系。这个压缩包包含的“体系结构图”很可能是以图形形式展示了Java的核心概念...

    深入理解Java虚拟机体系结构

    【深入理解Java虚拟机体系结构】 Java虚拟机(Java Virtual Machine,简称JVM)是Java平台的核心组成部分,它使得Java程序具有平台无关性,保证了“一次编译,到处运行”的特性。Java虚拟机主要负责加载类文件并...

    java体系笔记

    本笔记将深入探讨Java的各个核心概念和组成部分,构建一个全面的Java知识体系。 一、Java基础 1. Java语法:Java语法基于C++,但更加简化和安全。包括变量声明、数据类型(如基本类型、引用类型)、运算符、流程...

    JVM体系结构与GC调优

    了解JVM的体系结构和垃圾收集(Garbage Collection, GC)机制对于优化Java应用性能至关重要。 **1. JVM体系结构** JVM主要由以下几个组件构成: - **类装载器(Class Loader)**:负责加载.class文件到JVM内存中...

    JAVA入门.docx

    * 体系结构中立性:Java 程序在 Java 平台上被编译为体系结构中立的字节码格式,然后可以在实现这个 Java 平台的任何系统中运行。 * 可移植性:Java 语言的可移植性来源于体系结构中立性,另外,Java 还严格规定了...

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

    提供了访问该类在方法去内的数据结构的接口。 类加载有类加载器完成: 类加载器分为:Java虚拟机自带的加载器和用户自定义的类加载器; Java虚拟机自带的类加载器包括:启动类加载器,扩展类加载器,系统类加载器三...

    Java虚拟机规范(Java SE 8版) 带书签

    4. **类加载器体系**:JVM有多个类加载器,如bootstrap classloader、extension classloader和app classloader,它们协同工作,按照特定层次结构加载类。 5. **运行时数据区**:包括程序计数器、虚拟机栈、本地方法...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    ├─面试必问-架构杀手锏——java混乱的日志体系 │ java混亂日志体系源码揭秘.mp4 │ ├─面试必问-深入微服务之SpringBoot&Docker1 │ 深入微服务之SpringBoot&Docker.mp4 │ └─面试必问-聊聊哈希算法与HashMap

    w3school java & java web教程 飞龙整理 20141001

    Java以其“一次编写,到处运行”的理念,提供了跨平台的可移植性,这得益于其字节码(.class文件)的体系结构中立性。Java分为三个主要的体系: 1. **Java Standard Edition (JavaSE)**:适用于桌面应用和一般的...

    基于JAVA的学生通讯录管理系统设计和实现[文献综述].doc

    Java程序(后缀为java的文件)在Java平台上被编 译为体系结构中立的字节码格式(后缀为class的文件),然后可以在实现这个Java平台 的任何系统中运行。这种途径适合于异构的网络环境和软件的分发。 7、Java语言是可...

    JavaSetup8u101.zip 编程工具

    这种可移植性来源于体系结构中立性,另外,Java 还严格规定了各个基本数据类型的长度。Java 系统本身也具有很强的可移植性,Java 编译器是用 Java 实现的,Java 的运行环境是用 ANSI C 实现的。 Java是全能的!!!...

    Java2平台安全技术-结构,API设计和实现.rar

    本资料"Java2平台安全技术-结构,API设计和实现"聚焦于Java安全机制的深入理解和实践,涵盖了以下几个关键知识点: 1. **Java安全模型**:Java的安全模型基于沙箱机制,确保代码在执行时不会对系统造成破坏。它通过...

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

    Java基础面试题目主要涵盖了许多核心概念,包括语言特性、数据结构、并发处理、异常处理、类与对象的关系、以及Web开发相关的技术。以下是对这些知识点的详细解释: 1. **公共(public)、受保护(protected)、...

    Java期末考试题及答案.pdf

    通过Java的安全体系架构来确保Java代码的安全性。 * 解释性:Java代码是解释执行的,我们使用Java编译器将Java代码编译成字节码,这是一种中间代码,然后由Java解释器解释执行。 * 与平台无关:Java作为一种网络语言...

    深入Java虚拟机读书笔记1

    类装载体系结构包括启动类装载器和用户定义的类装载器,形成了层次结构。Bootstrap ClassLoader首先加载JRE的核心类库,然后用户定义的类装载器加载应用程序的类,它们之间通过委托模型协作工作,保证类的唯一性。 ...

    Java虚拟机规范中文版

    《Java虚拟机规范中文版》详细阐述了JVM的工作机制,是开发者深入理解Java技术体系的重要参考资料。以下是对该书内容的概览: 1. **JVM架构** JVM分为几个主要组件,包括类装载器、运行时数据区、执行引擎、本地...

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

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

Global site tag (gtag.js) - Google Analytics