JVM默认有三个类加载器:

  • Bootstrap Loader

    Bootstrap Loader通常有C编写,贴近底层操作系统。是JVM启动后,第一个创建的类加载器。

  • Extended Loader

    Extended Loader由Java编写,由Bootstrap Loader创建。JVM启动后,第二个被创建的类加载器。在Oracle JDK中,对应sum.misc.Launcher$ExtClassLoader($表示内部类)。

  • System Loader

    System Loader由Java编写,同样由Bootstrap Loader创建。JVM启动后,第三给被创建的类加载器。在Oracle JDK中,对应sum.misc.Launcher$AppClassLoader

     
     

JVM启动后,类加载器的创建顺序如下:

  1. JVM创建Bootstrap Loader;
  2. 由Bootstrap Loader创建Extended Loader;
  3. 设置Bootstrap Loader为Extended Loader的父类;
  4. 用Bootstrap Loader创建System Loader;
  5. 设置Extended Loader为System Loader的父类。

如下图:

从创建过程可见,类加载器间是有层级关系的

当类加载器有加载任务时,会先把加载任务交给父加载器,如果父加载器无法加载,才由自己加载。所以加载类的时候,会以Bootstrap Loader → Extended Loader → System Loader的加载类。如果所有加载器加载类失败,抛出java.lang.NoClassDefFoundError异常。

每个类加载器,会到其指定的目录下,根据类名加载类文件。三个默认类加载器的指定目录保持在JVM的系统属性里。

Bootstrap Loader

sun.boot.class.path

可以在编译时期,使用-bootclasspath指定。

Extended Loader

java.ext.dirs

System Loader

java.class.path

可以在运行程序时,使用-cp指令覆盖CLASSPATH系统环境变量。

可以使用System.getProperty()方法获取实际值。

 
 

三个默认类加载器在程序启动后,就无法更改它们的搜索目录。如果在程序运行过程中,打算动态加载其他路径下的类,可以创建java.net.URLClassLoader实例,使用新的类加载器。

URLClassLoader类创建实例时,需要java.net.URL数组作为参数指定新的类加载搜索路径。

ClassLoader loader = new URLClassLoader(new URL[] {new URL(pathA), new URL(pathB)});

loader.loadClass(clzName);

URLClassLoader类的实例,将由Bootstrap Loader创建,指定父加载器为System Loader

由于使用URL协议,可以指定远程服务器上的类文件,使用本地路径时,注意添加前缀"file:/"

 
 

类加载器可以使用loadClass()方法加载类,默认不会执行类的静态初始区块。但会在第一次新建该类实例的时候执行静态初始区块。

可以使用getParent()获取类加载器的父加载器。自定义对象默认用System Loader加载,可以使用Class.getClassLoader()获取加载该类的类加载器。

// 获取System Loader

ClassLoader sysClassLoader = Empty.class.getClassLoader();

// 获取Extended Loader

ClassLoader extClassLoader = sysClassLoader.getParent();

// 获取Bootstrap Loader

ClassLoader bootClassLoader = extClassLoader.getParent();

 
 

System.out.println(sysClassLoader);

System.out.println(extClassLoader);

System.out.println(bootClassLoader);

输入如下:

sun.misc.Launcher$AppClassLoader@73d16e93

sun.misc.Launcher$ExtClassLoader@15db9742

null

获取Extended Loader的父加载器时,返回值为null,但并不代表它没父加载器。因为Bootstrap Loader通常由C实现,在Java中没实际类实例来表示,所有会显示null

标准API的类(包括数组对象,包装器),都是由Bootstrap Loader加载的。

// 以下均输出null

System.out.println(String.class.getClassLoader());

System.out.println(int[].class.getClassLoader());

System.out.println(Integer.class.getClassLoader());

System.out.println(Class.class.getClassLoader());

 
 

同一个类文件,由同一个类加载器(实际加载的那个类加载器,注意加载任务会先向父加载器传递)多次加载,只有一个Class实例;如果由不同的类加载器加载,会由不同的Class实例。

参考资料:《Java学习笔记》 第17章

Java之类加载器(Class Loader)的更多相关文章

  1. java自定义类加载器

    前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是ec ...

  2. Java虚拟机类加载器及双亲委派机制

    所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...

  3. 深入探讨java的类加载器

    类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Ja ...

  4. java 中类加载器

    jar 运行过程和类加载机制有关,而类加载机制又和我们自定义的类加载器有关,现在我们先来了解一下双亲委派模式. java 中类加载器分为三个: BootstrapClassLoader 负责加载 ${ ...

  5. Java中的类加载器--Class loader

    学习一下Java中的类加载器,这个是比较底层的东西,好好学习.理解一下.  一.类加载器的介绍 1.类加载器:就是加载类的工具,在java程序中用到一个类,java虚拟机首先要把这个类的字节码加载到内 ...

  6. java高新技术-类加载器

    1.类加载器及委托机制的深入分析 > 类加载器的作用:一个java文件中的出现的类,首先要把这个类的字节码加载到内存中,这个类的信息放在硬盘的classPath下的class文件中,  把cla ...

  7. java面向对象--类加载器及Class对象

    类加载器 jvm 和 类的关系 当调用 java命令运行一个java程序时,会启动一个java虚拟机进程.同一个jvm的所有线程.所有变量都处于同一个进程里,都使用该jvm进程的内存区. jvm进程终 ...

  8. Java的类加载器

    一.类加载器的概念 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 ...

  9. Java的类加载器种类(双亲委派)

    Java类加载器采用双亲委派模型: 1.启动类加载器:这个类加载器负责放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别 ...

随机推荐

  1. 字符串(string)操作的相关方法

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. (个人开源)ffpanel --ffmpeg的GUI,让ffmpeg离开黑黑的命令行

    程序及源代码下载地址 :https://github.com/langsim/ffpanel

  3. PowerBuilder -- 未公开函数

    原文:http://blog.csdn.net/happymagic/article/details/51077322 @.已知一个DW中的某列的列名(在字符串变量中),以获得这个列对象的DWO 方法 ...

  4. 模式识别开发之项目---基于opencv的手势识别

    我使用OpenCV2.4.4的windows版本+Qt4.8.3+VS2010的编译器做了一个手势识别的小程序. 本程序主要使到了Opencv的特征训练库和最基本的图像处理的知识,包括肤色检测等等. ...

  5. 图像处理之基础---卷积及其快速算法的C++实现

    头文件: /* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), zmjerry@163.com * * This program is free so ...

  6. 在mac下搭建java开发环境

    刚刚从windows系统转到使用mac系统.感觉不是特别熟悉,须要一定的适应时间. 以下简介一下mac下搭建主要的java开发环境. 1.安装jdk 安装jdk1.7后,发现不须要进行环境变量配置,直 ...

  7. 【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA

    [BZOJ4999]This Problem Is Too Simple! Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2 ...

  8. Mac版 Intellij IDEA 激活

    第一步:修改这两个文件夹 进入跳转路径,输入 /private/etc/ 点击[前往] 同时加上: # Intellij IDEA0.0.0.0 account.jetbrains.com 第二部:在 ...

  9. wepy 实现 用户名登录与短信验证码登录

    wepy 实现 用户名登录与短信验证码登录

  10. python数据分析之:数据清理,转换,合并,重塑(一)

    DataFrame合并: merge运算是将一个或多个键将行链接起来.来看下面的这个例子: In [5]: df1=DataFrame({'key':['b','b','a','c','a','a', ...