JAVA基础知识之JVM-——类加载器
类加载器负责将.class文件加载到内存,并为其创建java.lang.Class对象,这个对象就代表这个类。
在Java中,通过包名+类名来唯一标识一个类,而在JVM中,要用 类加载器实例+包名+类名 来唯一标识一个类。 可见JVM中是不止一种类加载器的。
在JVM中,类加载器是成层次结构的, 这种层次结构自上而下分别是根类加载器(BootstrapLoader),扩展类加载器(extensionLoader)和系统类加载器(systemLoader)还有用户自定义类加载器
根类加载器(BootstrapLoader)
负责加载JAVA核心类(例如tr.jar)。 根类加载器是由JVM自身实现的(C/C++),而不是JAVA实现,更不是java.lang.ClassLoader的子类。
下面程序演示了根类加载器所加载的JAVA核心类库。
package jvmTest;
import java.net.URL;
import sun.misc.Launcher;
public class Boot {
public static void main(String[] args) {
/*
* 这里有可能报错 Access restriction: The type 'Launcher' is not API
* 只需要将 全局属性Project>preferences>java>Compiler>Errors/Warnings>
* 把右侧的【Deprecated and restricted API>Forbidden reference的Error】置为【Warning】.
*/
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for(int i = 0; i < urls.length; i++) {
System.out.println(urls[i].toExternalForm());
}
}
}
在我的环境中输入如下,
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/bin/default/jclSC170/vm.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/se-service.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/math.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/jlm.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmorb.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmorbapi.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmcfw.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmpkcs.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmcertpathfw.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmjgssfw.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmjssefw.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmsaslfw.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmjcefw.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmjgssprovider.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmjsseprovider2.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmcertpathprovider.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/xmldsigfw.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/xml.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/charsets.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/resources.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/rt.jar
file:/C:/Program%20Files%20(x86)/IBM/Java70/jre/lib/ibmgpu.jar
可以看到rt.jar包含在其中, 正因为加载了这些类库,我们才可以在程序中直接使用 System, String这样的类
扩展类加载器(extensionLoader)
负责加载来自JRE的扩展目录(\jre\lib\ext\ 或者 java.ext.dirs 系统属性指定的目录)中JAR包中的类, 我们也可以将自己的类放在这个目录下作为扩展类加载。
系统类加载器(systemLoader)
也称为应用类加载器, 负责加载下面几种类,
- JVM启动时加载来自 java命令的 -classpath选项的JAR包
- java.lang.path系统属性
- CLASSPATH环境变量
类的加载机制
- 全盘负责
当一个类加载器加载一个Class时,该Class所依赖的其他Class也将由相同类加载器加载。
- 父类委托
JVM加载一个Class时,会先使用其父类加载器来加载,所以一直迭代到最上层的加载器,一个类会最先由BootstrapLoader尝试加载,如果失败则由extensionLoader尝试加载,再失败则由systemLoader尝试加载,最后还失败则由自定义的类加载器来加载,如果依然失败,就会抛出错误。 父类委托机制可以防止类被重复加载,也更安全
所以常规加载顺序如下图 (图片引用自 http://blog.csdn.net/xyang81/article/details/7292380)

但是tomcat采用了完全相反的机制,先通过默认类加载器加载,如果失败,再找父类加载器加载。
这篇文章这样描述tomcat的加载过程(http://ifeve.com/classloader/)

下面例子演示了这种层次关系,
package jvmTest; import java.net.URL;
import java.util.Enumeration; public class Loader {
public static void main(String[] args) throws Exception {
// 获取系统类加载器
ClassLoader scl = ClassLoader.getSystemClassLoader();
System.out.println("系统类加载器(systemLoader): "+ scl);
// 获取系统 类加载器 的路径,通常由环境变量CLASSPATH指定,如果操作系统未指定CLASSPATH,则取当前路径
// 在ClassLoader类中定义的方法, public Enumeration<URL> getResources(String name)
// Enumeration比较古老,比较少用到,多数情况下都已经被Iterator取代
Enumeration<URL> eml= scl.getResources("");
while(eml.hasMoreElements()) {
System.out.println("系统加载器路径: "+eml.nextElement());
}
// 获取系统加载器的父加载器,得到扩展类加载器
ClassLoader ecl = scl.getParent();
System.out.println("扩展加载器(extensionLoader): "+ ecl);
System.out.println("扩展加载器路径: "+ System.getProperty("java.ext.dirs"));
System.out.println("扩展加载器的parent: "+ ecl.getParent());
}
}
执行结果,
系统类加载器(systemLoader): sun.misc.Launcher$AppClassLoader@4be822c2
系统加载器路径: file:/C:/Users/IBM_ADMIN/PROJECT/CrazyJAVA/PROJECT_JavaBasic/bin/
扩展加载器(extensionLoader): sun.misc.Launcher$ExtClassLoader@cb289176
扩展加载器路径: C:\Program Files (x86)\IBM\Java70\jre\lib\ext
扩展加载器的parent: null
执行结果可以看到扩展类加载器的parent从逻辑上来讲应该是根类加载器,但实际却是null,这是因为根类加载器是用C++实现的,JAVA无法直接访问。
- 缓存机制
缓存机制保证加载过的Class被缓存起来,当加载新类时,先进缓存查询是否已经加载,只有缓存中没有的时候才进行加载,这样会显著提高性能。
reference
深入浅出ClassLoader
http://ifeve.com/classloader/
深入分析Java ClassLoader原理
http://blog.csdn.net/xyang81/article/details/7292380
JAVA基础知识之JVM-——类加载器的更多相关文章
- JAVA基础知识之JVM-——自定义类加载器
JVM中除了根加载器之外其他加载器都是ClassLoader的子类实例, 可以通过扩展ClassLoader的子类,通过重写方法来实现自定义的类加载器. ClassLoader中有两个关键的方法如下, ...
- 【java虚拟机系列】JVM类加载器与ClassNotFoundException和NoClassDefFoundError
在我们日常的项目开发中,会经常碰到ClassNotFoundException和NoClassDefFoundError这两种异常,对于经验足够的工程师而言,可能很轻松的就可以解决,但是却不一定明白为 ...
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架
类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...
- java 基础知识学习 JVM虚拟机参数配置
1) 设置-Xms.-Xmx相等: 2) 设置NewSize.MaxNewSize相等: 3) 设置Heap size, PermGen space: Tomcat 的配置示例:修改%TOMCAT_H ...
- JAVA基础知识|java虚拟机(JVM)
一.JVM简介 java语言是跨平台的,兼容各种操作系统.实现跨平台的基石就是虚拟机(JVM),虚拟机不是跨平台的,所以不同的操作系统需要安装不同的jdk版本(jre=jvm+类库:jdk=jre+开 ...
- Java内存管理-掌握自定义类加载器的实现(七)
勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分析了ClassLoader的类加载相关的核心源码,也简单介绍了ClassLoa ...
- 沉淀,再出发:Java基础知识汇总
沉淀,再出发:Java基础知识汇总 一.前言 不管走得多远,基础知识是最重要的,这些知识就是建造一座座高楼大厦的基石和钢筋水泥.对于Java这门包含了编程方方面面的语言,有着太多的基础知识了,从最初的 ...
- java基础知识一览(二)
一.java基础知识 1.一个文件中只能有一个public的类,因为他的类名要求和文件名相同. 2.classpath变量可以设置其它目录下的类. 例如:类文件所在目录是:F:\Javajdk,那么没 ...
- 「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !
本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指南」一份涵盖大 ...
- 从 1 开始学 JVM 系列 | JVM 类加载器(一)
从 1 开始学 JVM 系列 类加载器,对于很多人来说并不陌生.我自己第一次听到这个概念时觉得有点"高大上",觉得只有深入 JDK 源码才会触碰到 ClassLoader,平时都是 ...
随机推荐
- Ways to access Oracle Database in PostgreSQL
Today, organizations stores information(data) in different database systems. Each database system ha ...
- "数学口袋精灵"bug的发现及单元测试
1.项目内容: 团队项目:二次开发 至此,我们有了初步的与人合作经验,接下来投入到更大的团队中去. 也具备了一定的个人能力,能将自己的代码进行测试.接下来尝试在别人已有的基础上进行开发. 上一界51冯 ...
- HDU 4031 Attack(离线+线段树)(The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4031 Problem Description Today is the 10th Annual of ...
- hdu5381 The sum of gcd
莫队算法,预处理出每个数字往后的gcd情况,每个数字的gcd只可能是他的因子,因此后面最多只可能有logn种,可以先预处理出,然后套莫队算法,复杂度O(n*sqrt(n)*log(n)). 代码 #i ...
- PHP V5.2 中的新增功能,第 1 部分: 使用新的内存管理器
PHP V5.2:开始 2006 年 11 月发布了 PHP V5.2,它包括许多新增功能和错误修正.它废止了 5.1 版并被推荐给所有 PHP V5 用户进行升级.我最喜欢的实验室环境 —— Win ...
- C#与js的各种交互
今天遇到一个问题,查到不错的资料,放上来记录一下,以防忘记地址,算是我的笔记吧! 很多人都向在服务器端调用客户端的函数来操作,也就是在asp中调用javascript脚本中已经定义好的脚本函数.经过研 ...
- mysql设置时区方法
set global time_zone = '+2:00'; ##修改mysql全局时区 set time_zone = '+2:00'; ##修改当前会话时区 flush privileges; ...
- SQL 中常见的系统存储过程
-- 来源于网络 -- 更详细的介结参考联机帮助文档 xp_cmdshell --*执行DOS各种命令,结果以文本行返回. xp_fixeddrives --*查询各磁盘/分区可用空间 xp_logi ...
- SLC、MLC和TLC三者的区别
SLC=Single-LevelCell,即1bit/cell,速度快寿命长,价格超贵(约MLC3倍以上的价格),约10万次擦写寿命 MLC=Multi-LevelCell,即2bit/cell,速度 ...
- php使用过滤器filter_var轻松验证邮箱url和ip地址等
以前使用php的时候还不知道有过滤器filter这玩意,那时候判断邮箱.url和ip地址格式是否符合都是用正则表达式.后来随着使用的逐渐深入,才知道在php中也可以使用内置的函数库过滤器filter来 ...