在做Java开发时了解Java类加载机制是非常好的。而对类加载机制的基本理解对Java开发人员处理类加载器(ClassLoader)相关的异常也很有帮助。

类加载器委托机制

Java类的装载是通过类加载器(CL)来完成的,这些类加载器负责将类加载到JVM中。简单的应用可以使用java平台自带的类加载器来加载自身的类,而稍微复杂一些的应用则倾向于自定义类加载来加载自身的类。

在java中类加载器是以树状结构组织的。通过请求一个类加载器并通过在其缓存中查找来确定某个类是否已被加载。如果在缓存中已经有该类,那么CL直接返回;否则,该类加载器委托其父类加载器来加载该类。如果这个类加载器没有父类或者父类不能加载这个类则会抛出ClassNotFoundException异常,此时被请求的类加载器会尝试去在它自身的路径下来查找并加载需要被加载类的类文件。如果找到了这个类,就将其返回;否则会抛出ClassNotFoundException异常。其中缓存的查找方式为递归的从子类到父类查找,直到到达树(译注:类加载器已树状结构组织)的根节点或者在缓存中找到需要的类为止。如果缓存搜索已到达根节点,则类加载器会从父类到子类再次展开递归来加载需要的类。总的来说顺序如下:

1.缓存

2.父类

3.子类

这种机制确保类会类会被最接近根结点的类加载器加载。请谨记,父类加载器总是有优先加载类的权限。而这很重要的作用就是确保核心java类都被bootstrap类加载器加载,这个类加载器是用来保证正确版本的类加载,如java.lang.Object。此外,bootstrap类加载器还保证一个类加载只能看到自身或其父类(或父类的父类等)加载的类,而不能看到其子类以及兄弟类(译注:继承同一个父类的类称为兄弟类)所加载的类。

下图阐明了类加载器的层级关系。根加载器是bootstrap类加载,该加载器是通过native方法实现,并且不能在java代码中实例化。

BootStrap之后便是扩展类加载器,该加载器的主要责任是从扩展目录中加载类并且在新的JVM中不修改用户classpath的情况下来提供简单访问JVM扩展的能力。而系统或者应用类加载器则负责从环境变量CLASSPATH中指定的路径来加载类;这种类加载器可以通过调用ClassLoader.getSystemClassLoader()方法获得。

类加载阶段

具体的类加载可以分为3个阶段:物理加载,链接,初始化。

1在物理加载阶段,要求类可以在指定的classpath路径中被找到。如果可以找到类文件,通过读取类文件来加载字节码。这个处理过程给出了单个类对象的一个基本内存结构,但是像方法、字段以及对以其他类的一些引用这些概念在这个阶段是不知道的。

2链接阶段可以拆分为3个主要阶段,因为这个阶段比较复杂:

2.1通过类加再起校验字节码,该过程会在字节码上执行一系列校验。

2.2类准备。这个阶段准备必要的数据结构,表示类中所定义的字段、方法以及所实现的接口。

2.3解析某个特定类中所有的其他类引用。类可以通过很多途径被应用,具体如下

2.3.1

父类

2.3.2

接口

2.3.3

字段类型

2.3.4

方法返回值类型

2.3.5

在方法中使用的本地变量类型

3在初始化阶段,这个类中包含的所有初始化块都会被执行,一遍静态变量都会被初始化为默认值。

有趣的是类加载可以通过延迟加载机制来实现,因此一部分只是在第一次使用的时候才被加载而不是一开始就加载。

异常

在处理类加载问题时最大的挑战在于问题很难在类加载这个处理过程体现出来,而是在之后使用这个类的时候才会被体现出来。以下是类加载时两个相关的异常以及造成对应异常的可能原因:

ClassNotFoundException

l当被加载的类相关文件、目录或者其他资源没有添加到对应了类加载器或者父类加载器时

l当类加载器的父类设置错误时

l当类加载器使用错误时

NoClassDefFoundError

l当被加载的类相关文件、目录或者其他资源没有添加到对应了类加载器或者父类加载器时

l当类加载器的父类设置错误时

l当一个类被加载时,该类中所包含的引用对该类的类加载器不可达时,例如加载器的子类

1. 本文由程序员学架构翻译

2. 本文译自 http://www.techjava.de/topics/2008/01/java-class-loading/

3. 转载请务必注明本文出自:程序员学架构(微信号:archleaner)

4. 更多文章请扫码:

java类加载器可以从互联网加载,Java类加载器深入解析(2)相关推荐

  1. java版如何使区块常加载,Java类加载机制 - suer27zhu的个人空间 - OSCHINA - 中文开源技术交流社区...

    首先上图 如图所示,Java类加载机制的六个阶段 Java代码编译完成后会生成对应的class文件,接着我们运行java命令的时候,其实是启动了JVM虚拟机执行class字节码文件的内容.大致分为六个 ...

  2. java 找不到或无法加载,java提示找不到或无法加载主类

    问题: 使用java命令运行.class文件时出现:"错误: 找不到或无法加载主类" 解决方法: 使用 java 包名+类名执行,如下:在src下使用 java com.lznb. ...

  3. java applet 浏览器_浏览器不能加载Java中Applet小程序

    展开全部 要确e68a8462616964757a686964616f31333363373736保浏览器可以运行applet,需要执行如下步骤: 1.确保applet在eclipse是可以运行的(本 ...

  4. 类加载器 java委托机制_解析Java虚拟机中类的初始化及加载器的父委托机制

    类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有 ...

  5. java 类加载器的理解及加载机制?

    通过 java 命令运行 java 程序的步骤就是指定包含 main 方法的完整类名以及一个 classpath 类路径,类路径可以有多个,对于直接的 class 文件路径就是 class 文件的根目 ...

  6. 深入理解Java虚拟机二(类加载器和类的加载过程)

    类加载器子系统作用 类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识. ClassLoader只负责class文件的加载,至于它是否可以运行,则由Ex ...

  7. java 内部类 加载_举例讲解Java的内部类与类的加载器

    内部类 class A { //Inner1 要在 A 初始化后 才能使用,即要被A的对象所调用 class Inner1 { int k = 0; // static int j = 0; //A加 ...

  8. java类加载过程_java类的加载过程

    在这本书里面,在讲到类初始化的五种情况时,提及了一个比较有趣的事情.先来看看下面的代码 public class SubClass { static{ System.err.println(" ...

  9. java class加载_Java 类加载

    从一个诡异的问题说起 测试案例一: packageecut.classloader;public classSun {protected static int a = 100;protected st ...

最新文章

  1. 创建java的可执行文件
  2. oracle 怎么调整emctl,emca和emctl的日常用法及实例(经验保存)
  3. 面试常见问题之实现bind函数
  4. java对数组进行排序_用Java对数组进行排序所需的最少交换
  5. fastreport iif小于条件_杭州灭菌柜验证需要什么条件
  6. Oracle异常汇总
  7. 2016年1月书单推荐
  8. 从入门到入土:[SEED-Lab]-SQL注入攻击|SQL Injection Attack Lab|详细说明|实验步骤|实验截图
  9. C#中不失真生成缩略图
  10. Sketch for Mac(矢量绘图工具)
  11. c++编程迷宫小游戏
  12. NLP最简单中文分词介绍
  13. CSDN-JayChou测试
  14. win10打印机安装提示无法连接到打印机
  15. 数据结构复习题(二)
  16. 神经网络的具体应用实例,各种神经网络的应用
  17. uniapp上高德(百度)地图API的使用(APP安卓)
  18. 人力资源管理的现状及发展趋势
  19. 贵州省大数据基地规划编制工作组到省教育厅调研教育信息化工作
  20. 小游戏与H5游戏对比与梳理

热门文章

  1. MLX90640 开发 微型红外成像仪
  2. blueStacks模拟器安装应用慢的问题
  3. Input 如何取消输入自动提示
  4. jqGrid表格实例
  5. windows10 的rocketMQ安装并测试
  6. 券商如何借助企业微信、小程序、视频号提高营收转化?
  7. element-ui的table表格数据选择,分页,跨页保存数据的方法
  8. 中国省城市列表(中国的性格+拼音)
  9. 吐槽memoQ | 翻译软件也能有在线字典/语料?
  10. linux离线安装docker和docker-compose