先回顾一下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. Android通过tcpdump抓包(wifi, 2g, 3g都可以)

    http://blog.csdn.net/deng529828/article/details/20646197 1. 手机要有root权限 2. 下载tcpdump   http://www.str ...

  2. MS SQLserver数据库安装

    SQL2008的安装 1,双击打开setup安装文件 2,点击“全新安装或向现有安装添加功能” 3,安装程序支持规则,安装完之后,点击确定 4,输入产品的密钥,点击下一步 5,弹出“安装程序支持文件” ...

  3. IO流详解(半教材类型)

    这两天学习了IO流,整理了一些理论知识点,仅供参考. java流概述 一 流 从操作系统层面和文件系统,数据保存相关的是所有语言都具备的一个基本功能,java专门开发了一个包:java.io.*;ja ...

  4. Swift学习的新工具---REPL

    从xcode6.1开始,苹果官方提供了一个新的辅助开发swift的工具,即repl(read eval print loop) OS X Yosemite系统下,打开终端应用程序,输入swift: 如 ...

  5. 06链队列_LinkQueue--(栈与队列)

    #include "stdio.h" #include "stdlib.h" #include "io.h" #include " ...

  6. JavaScript DOM编程艺术 - 读书笔记1-3章

    1.JavaScript语法 准备工作 一个普通的文本编辑器,一个Web浏览器. JavaScript代码必须通过Html文档才能执行,第一种方式是将JavaScript代码放到文档<head& ...

  7. 将博客搬迁至CSDN

    CSDN不给我搬家就算了....我自己搬= = http://blog.csdn.net/ourfutr2330

  8. 使用XmlPullParser对xml进行读取

    XML文件是一种标记性语言;在开发中经常在接口交互时被用作报文传输或者把自定义的类序列化为XML的形式存储到数据库.正因为XML文件这么常用,使用JAVA对XML文件进行读写操作是每一个开发人员必须掌 ...

  9. php中位运算的应用:货品的状态

    效果如下图: 分析:用一个整数的二进制可以记录32状态 00000000 00000000 00000000 00000000  >>=0 从右往左保存这三个的状态: 精品选中,第一位设置 ...

  10. WF4的数据库 表

    WF4的数据库 表 SQL 建表 SqlPersistenceProviderSchema.sql InstanceData 实例数据表 SqlPersistenceService_Schema.sq ...