先回顾一下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. 微信公众账号 Senparc.Weixin.MP SDK 开发教程

    http://www.cnblogs.com/szw/archive/2013/05/14/weixin-course-index.html 微信公众账号 Senparc.Weixin.MP SDK ...

  2. Cisco交换机中的flash,Rom,RAM,nvram的区别

    Flash内存,也叫闪存,是路由器当中常用的一种内存类型.它是可读写的存储器,在系统重新启动或关机之后仍能保存数据.Flash中存放着当前使用中的IOS(路由器操作系统). 只读内存(ROM)在Cis ...

  3. JavaScript高级程序设计(三):基本概念:数据类型

    特别注意:ECMAScript是区分大小写的. 一.变量 1.ECMAScript的变量是松散型的.所谓松散型就是可以用来保存任何类型的数据.即每个变量仅仅是一个用于保存值的占位符而已.定义变量时要使 ...

  4. English Audio-Books

    Downloadble English Audio-Books websites 一.网站 1.可听书 2.山寨 3.有声书库 4.audioboom.com 5.豆瓣小站 6.AudioBook 二 ...

  5. Makefile当中宏定义传递字符串

    前几天遇到类似的问题[http://bbs.chinaunix.net/thread-1589386-1-1.html]: 在Makefile里面定义一个字符串在程序里面使用, CFLAGS += - ...

  6. mysql innodb 数据打捞(三)innodb 簇不连接页的扫描提取(计划)

    操作系统簇大小一般是4K,而innoDB的页大小一般是16K,那么就有可能16K的页没有存储在连续的簇中,这样扫描软件就不会扫描出来这样的页面.为了解决这个问题,决定给软件增加半页扫描功能. 在第一次 ...

  7. C++ 中的“ !” 运算

    在介绍“ !”运算之前,我们要知道一个变量n,如果n>0,那么我们可以在逻辑上叫它“真”,如果n<=0 ,那么我们可以在逻辑上叫它“假”. n为真时,!n就为假(false),转换为整型值 ...

  8. ubuntu12.10可用更新源

    ubutnu12.10自带的更新源已经失效,国内各大服务器的更新源,无论是网易.搜狐还是教育网的因此也失效了.附件是ubuntu12.10目前的可用更新源. 将地址中的“us.archive”换成“o ...

  9. spl_autoload_register array参数

    spl_autoload_register (PHP 5 >= 5.1.2) spl_autoload_register — 注册给定的函数作为 __autoload 的实现 说明¶ bool  ...

  10. WPF中Application.Current的使用

    WPF程序对应一个Application对象,当前的Application对象可以通过Application.Current获取,通过获取到的Application对象,我们可以做以下的事情: App ...