先回顾一下classpath

classpath的作用:

classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类。

指定classpath的方式一: 
        设置环境变量CLASSPATH,多个路径之间使用英文的分号隔开,也可以指定为jar包路径。 
         示例:CLASSPATH=c:/myclasses/;c/mylib/aa.jar;c:/mylib/bb.jar;. 
         注意:在Windows中不区分大小写,所以指定的环境变量名为classpath或是ClassPath都一样。

指定classpath的方式二: 
         在执行java命令时通过-classpath参数指定。 
         示例:java -classpath c:/myclasses/;c:/mylib/aa.jar cn.itcast.MainApp 
         注意:这样就会只是用这个参数指定的classpath,找不到类就报错,不会使用CLASSPATH环境变量!

指定classpath时各个路径的顺序: 
        试验的结论是 按classpath中指定的顺序,先从前面的路径中查找,如果找不到,在从下一个路径中查找,直到找到类字节码或是报NoClassDefFoundError。 
另外一种指定类路径方式: 
        把类字节码文件打成jar包,并放到JRE的lib/ext/目录下,这样在执行时就可以直接找到这个类而不需要指定classpath了。

类加载器与classpath

从上一个文章中我们知道了类加载器默认使用三个: 
1,Bootstrap ClassLoader,启动类加载器,负责加载核心Class(即所有java.*开头的Class)。 
2,Extension ClassLoader,扩展类加载器,负责加载存放在JRE的lib/ext/目录下的jar包中的Class。 
3,Application ClassLoader,应用程序类加载器,负责加载应用程序自身的类(CLASSPATH目录中的Class)。

分析ExtClassLoader

  Extension ClassLoader负责加载扩展类路径中的类(默认为JRE的lib/ext/目录) ,也就是说只要把jar包放到这个目录中,就可以直接使用里面的类字节码而不需要指定classpath !注意这要求一定要在这个目录中放jar包,直接把.class文件放到这个目录中不行。分析一下源码(sun.misc.Launcher$ExtClassLoader类):

static class ExtClassLoader extends URLClassLoader {
private File[] dirs; // 先看这个方法
public static ExtClassLoader getExtClassLoader() throws IOException {
// 调用getExtDirs()方法获取配置的扩展类路径
final File[] dirs = getExtDirs();
try {
// 使用getExtDirs()方法返回的路径生成一个新的ClassLoader实例
return (ExtClassLoader) AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws IOException {
int len = dirs.length;
for (int i = 0; i < len; i++) {
MetaIndex.registerDirectory(dirs[i]);
}
return new ExtClassLoader(dirs);
}
});
} catch (java.security.PrivilegedActionException e) {
throw (IOException) e.getException();
}
} // 再看这个方法
private static File[] getExtDirs() {
// 获取配置的扩展类路径
String s = System.getProperty("java.ext.dirs");
File[] dirs;
if (s != null) {
StringTokenizer st = new StringTokenizer(s, File.pathSeparator);
int count = st.countTokens();
dirs = new File[count];
for (int i = 0; i < count; i++) {
dirs[i] = new File(st.nextToken());
}
} else {
dirs = new File[0];
}
return dirs;
} // 其他代码略
...
}

Application ClassLoader负责加载CLASSPATH目录中的Class ,也就是说classpath是给这个类加载器用的。分析一下源码(sun.misc.Launcher$AppClassLoader类):

static class AppClassLoader extends URLClassLoader {

  public static ClassLoader getAppClassLoader(final ClassLoader extcl) throws IOException {
// 获取配置的classpath路径
// 注1:可以通过设置classpath环境变量改变java.class.path的值。
// 注2:也可以在程序中使用System.setProperty("java.class.path", "newpath")改变java.class.path的值。
final String s = System.getProperty("java.class.path");
final File[] path = (s == null) ? new File[0] : getClassPath(s); // 使用classpath中的路径生成一个新的ClassLoader实例并返回
return (AppClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
URL[] urls = (s == null) ? new URL[0] : pathToURLs(path);
return new AppClassLoader(urls, extcl);
}
});
} // 其他代码略
...
}

当AppClassLoader遇上ExtClassLoader

如果JRE的lib/ext/目录下的jar包有某个类,我们指定的classpath中也有这个类,会怎么样呢?想想类加载查找类字节码的策略!结论是会执行lib/ext/xx.jar中的类! 因为类加载器使用委托模式进行类加载,并且ExtClassLoader是AppClassLoader的上级,所以AppClassLoader会先让ExtClassLoader加载。如果父的类加载器没有找到,自己才会加载。

结论: 
1,把jar包放到扩展类路径中就可以直接使用其中的类(默认是JRE的lib/ext/目录)
2,classpath是给AppClassLoader配置的。 
3,如果扩展类路径中有某个类,classpath中也有这个类,则会使用扩展类路径中的类。

http://www.tuicool.com/articles/bQFnqmi

分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码的更多相关文章

  1. Java:类加载器(ClassLoader)

    听上去很高端,其实一般自定义类加载器不需要用户去实现解析的过程,只要负责实现获取类对应的.class字节流部分就ok了,摘录深入理解Java虚拟机的一段话 虚拟机设计团队把类加载阶段中的“通过一个类的 ...

  2. 仿酷狗音乐播放器开发日志二十四 选项设置窗体的实现(附328行xml布局源码)

    转载请说明原出处,谢谢~~ 花了两天时间把仿酷狗的选项设置窗体做出来了,当然了只是做了外观.现在开学了,写代码的时间减少,所以整个仿酷狗的工程开发速度减慢了.今天把仿酷狗的选项设置窗体的布局代码分享出 ...

  3. Java基础-类加载机制与自定义类Java类加载器(ClassLoader)

    Java基础-类加载机制与自定义类Java类加载器(ClassLoader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于类加载器的概念和分类我就不再废话了,因为我在之前的笔 ...

  4. java笔记--理解java类加载器以及ClassLoader类

    类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...

  5. JVM的艺术—类加载器篇(二)

    分享是价值的传递,喜欢就点个赞 引言 今天我们继续来深入的剖析类加载器的内容.上节课我们讲了类加载器的基本内容,没看过的小伙伴请加关注.今天我们继续. 什么是定义类加载器和初始化类加载器? 定义类加载 ...

  6. Java的类加载器

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

  7. 7. 通过JDBC源码来分析线程上下文类加载器以及SPI的使用

    目录 1. 什么是全盘负责委托机制 2. 为什么需要有线程上下文类加载器 2.1 使用JDBC的例子,分析为什么双亲委托机制不能实现要求 2.2 线程上下文类加载器的作用 3. 线程上下文类加载器的使 ...

  8. java自定义类加载器

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

  9. 深入理解Java虚拟机 - 类加载器

    引子:       类加载器(classloader)是独立于虚拟机之外,可以独立实现的代码模块.     OSGi使用了类加载器的这一特点实现其热插拔的特性       Java同C++等语言不通, ...

随机推荐

  1. 安装.NET Framework组件时,电脑意外重启后再次安装失败

    因为软件运行环境需要安装.Net Framework,我安装的是2.0sp版本,可以安装过程中计算机意外关闭,重新打开后再次安装却出现安装失败的提示,具体内容是: 产品: Microsoft .NET ...

  2. cocos2d-x实战 C++卷 学习笔记--第4章 使用标签

    前言: 介绍cocos2d-x中 标签类. cocos2d-x中 标签类 主要有三种:LabelTTF, LabelAtlas, 和 LabelBMFont.此外,在Cocos2d-x 3.x之后推出 ...

  3. iOS开发——图片轮播图+单选选项

    由于公司开发需要,需要滚动每道评测题, 并且一道评测题单项选择,按钮和文字都可点击选中 (单选比多选复杂一点,但是原理差不多) 1.当初任务紧,代码也没有优化,仅供思路参考,先放几张图 2.代码部分 ...

  4. C#下如何用NPlot绘制期货股票K线图(1)?

    [简介] 作为一名专业程序化交易者,编程是一个程序员的基本功,本文是作者在做的一个期货CTP项目中有关K线绘图的一部分,偿试类MT4中图表 设计而写,在编写绘图时,查阅了相关资料,感觉还是用NPlot ...

  5. C++动态二维数组的创建

    两种方式. 一,二级指针,创建2行3列的动态二维数组. 这里,p指向的是2个地址,这两个地址各指向长度为3的一维整型数组. 在内存中,每行元素内部顺序排列.两行元素的首地址不同,p[1]与p[2]存放 ...

  6. Headfirst设计模式的C++实现——状态模式(State)

    state.h #ifndef _STATE_H_ #define _STATE_H_ class GumballMachine; class State { public: ; ; ; ; Stat ...

  7. Cassandra1.2文档学习(10)—— 插入和更新数据

    参考数据:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/dml/dml_about_ ...

  8. Cassandra1.2文档学习(5)—— Snitch

    参考资料:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/architecture/a ...

  9. Fluid Shopping Website 开发阶段性总结——第一周

    开发目的: 可链接微信公众号,无论是桌面端.移动端完美兼容,给用户提供不逊于原生App的用户体验.作为一个软件,有充分的可扩展性,便于未来增强开发.同时给一些正在尝试做OTO的朋友们提供一个平台,因为 ...

  10. codeforces 630K - Indivisibility

    K. Indivisibility 题意:给一个n(1 <= n <= 10^18)的区间,问区间中有多少个数不能被2~10这些数整除: 整除只需要看素数即可,只有2,3,5,7四个素数: ...