Java之类加载器(Class Loader)
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启动后,类加载器的创建顺序如下:
- JVM创建Bootstrap Loader;
- 由Bootstrap Loader创建Extended Loader;
- 设置Bootstrap Loader为Extended Loader的父类;
- 用Bootstrap Loader创建System Loader;
- 设置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)的更多相关文章
- java自定义类加载器
前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是ec ...
- Java虚拟机类加载器及双亲委派机制
所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...
- 深入探讨java的类加载器
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Ja ...
- java 中类加载器
jar 运行过程和类加载机制有关,而类加载机制又和我们自定义的类加载器有关,现在我们先来了解一下双亲委派模式. java 中类加载器分为三个: BootstrapClassLoader 负责加载 ${ ...
- Java中的类加载器--Class loader
学习一下Java中的类加载器,这个是比较底层的东西,好好学习.理解一下. 一.类加载器的介绍 1.类加载器:就是加载类的工具,在java程序中用到一个类,java虚拟机首先要把这个类的字节码加载到内 ...
- java高新技术-类加载器
1.类加载器及委托机制的深入分析 > 类加载器的作用:一个java文件中的出现的类,首先要把这个类的字节码加载到内存中,这个类的信息放在硬盘的classPath下的class文件中, 把cla ...
- java面向对象--类加载器及Class对象
类加载器 jvm 和 类的关系 当调用 java命令运行一个java程序时,会启动一个java虚拟机进程.同一个jvm的所有线程.所有变量都处于同一个进程里,都使用该jvm进程的内存区. jvm进程终 ...
- Java的类加载器
一.类加载器的概念 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 ...
- Java的类加载器种类(双亲委派)
Java类加载器采用双亲委派模型: 1.启动类加载器:这个类加载器负责放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别 ...
随机推荐
- Minify把CSS和JS压缩和削减
Minify把CSS和JS压缩和削减(Minify:去掉空格回车符等),以及把多个CSS,JS文件整合到一个文件里.不要以为你的大带宽没有必要进行这类优化.使用它的理由更重要的是文件合并,而不是压缩, ...
- 一致性哈希算法(c#版)
最近在研究"一致性HASH算法"(Consistent Hashing),用于解决memcached集群中当服务器出现增减变动时对散列值的影响.后来 在JAVAEYE上的一篇文章中 ...
- Linux XMind
XMind这个软件好像不错的样子,至少在Windows/Linux/Mac下都可以工作,作为FreeMind的替代品应该是没什么问题(还有一个vym貌似也可以,可能没有XMind好,毕竟XMind有公 ...
- 【Linux】OpenWRT的无线设置注意事项——从2.4G到5G,hwmode不简单
硬件说明: 操作系统:OpenWRT 网卡:AR9220R52Hn 网卡驱动:ath9k OpenWRT在刷机完成之后,并不会自动开启无线功能,需要手动修改配置文件,然后重启网络服务.管理无线功能的配 ...
- HDFS源码分析心跳汇报之周期性心跳
HDFS源码分析心跳汇报之周期性心跳,近期推出!
- 16 redis之sentinel运维监控
一:sentinel运维监控 Sentinel不断与master通信,获取master的slave信息. 监听master与slave的状态 如果某slave失效,直接通知master去除该slave ...
- 计算机器内存数量+引入和显示ARDS成员
[1]README 1.1) 本代码在于读取内存中多个 内存段的地址范围描述符结构体(ARDS),有多少个内存段可以用: 1.2) source code and images in the blog ...
- C - The C Answer (2nd Edition) - Exercise 1-1
/* Run the "hello, world" program on your system. Experiment with leaving out parts of the ...
- <转> Struct 和 Union区别 以及 对内存对齐方式的说明
转载地址:http://blog.csdn.net/firefly_2002/article/details/7954458 一.Struct 和 Union有下列区别: 1.在存储多个成员信息时,编 ...
- CentOS6.5安装MySQL5.6 过程记录
刚开始,还不太懂,直接上了MySQL5.7版本的二进制安装,结果遇到了各种问题,从5.6到5.7还是做了很大改变的,比如mysql_install_db的文件位置变更到了/bin文件下等等,觉得现在用 ...