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

先回顾一下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的源码,布布扣,bubuko.com

时间: 2024-11-08 03:14:42

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

Java:类加载器(ClassLoader)

听上去很高端,其实一般自定义类加载器不需要用户去实现解析的过程,只要负责实现获取类对应的.class字节流部分就ok了,摘录深入理解Java虚拟机的一段话 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类加载器” 实现类加载器需要继承ClassLoader这个抽象类,用户只要实现其中的findClass方法即可.在该类的javadoc中给出了这样一个示

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

转载请说明原出处,谢谢~~ 花了两天时间把仿酷狗的选项设置窗体做出来了,当然了只是做了外观.现在开学了,写代码的时间减少,所以整个仿酷狗的工程开发速度减慢了.今天把仿酷狗的选项设置窗体的布局代码分享出来,给学习duilib布局的朋友做个demo.现在编写的仿酷狗选项设置窗体和原酷狗的窗体不细看几乎看不出差别,控件的布局位置和原酷狗最多只有几个像素的位置差别. 先来看一下原酷狗的选项设置窗体的其中一个页面: 如果还不太会布局的朋友可以先看我前些日子写的关于duilib布局的博客<duilib各种布

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

类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制.JVM中用来完成上述功能的具体实现就是类加载器.类加载器读取.class字节码文件将其转换成java.lang.Class类的一个实例.每个实例用来表示一个java类.通过该实例的newInstance()方法可以创建出一个该类的对象. 类的生命周期: 类从加载到虚拟机内存到被从内存中释放,经历的

Java 之 类加载器

一.类加载器概述 在开发中会遇到 java.lang.ClassNotFoundException 和 java.lang.NoClassDefError,想要更好解决这类问题,或者在一些特殊的应用场景,比如需要支持类的动态加载或需要对编译后的字节码文件进行加密解密操作,那么需要你自定义类加载器,因此了解类加载器及其加载机制成为了Java开发必备技能之一. 二.四种类加载器 1.引导类加载器(Bootstrap Classloader),又称为根类加载器 它负责加载 Java 的核心库(JAVA

java自定义类加载器

前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是eclipse项目中的bin目录里),然后通过java反射机制,获取main方法并执行..class文件名称固定.当 A.class文件更新的时候,问题出现了,main方法的执行结果总和第一次的执行结果相同. 程序流程 代码提交->接收代码->编译成A.class文件->java反射->m

团队项目 NABCD分析java音乐播放器

NABCD分析java音乐播放器 程设计题目:java音乐播放器 一.课程设计目的 1.编程设计音乐播放软件,使之实现音乐播放的功能. 2.培养学生用程序解决实际问题的能力和兴趣. 3.加深java中对多媒体编程的应用. 二.课程设计的要求 利用学到的编程知识和编程技巧,要求学生: 1.系统设计要能完成题目所要求的功能,设计的软件可以进行简单的播放及其他基本功能. 2.编程简练,可用,尽可能的使系统的功能更加完善和全面 3.说明书.流程图要清楚. 三.课程设计内容 1.课程设计的题目及简介 音乐

java不同类加载器对instanceof关键字运算的影响

内容:对于任意的一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类空间.只要加载类的类加载器不同的话,那么这个两个类就必定不相等(包括equals()方法,instanceof()方法).此时,虚拟机中存在两个ClassLoaderTest,一个是由系统应用程序类加载器加载的,另一个是由我们定义的类加载器加载的.一个简单的例子说明:注意getResourceAsStream的应用:Class.getResourceAsStream

深入java虚拟机-类加载器

此系列为深入java虚拟机(周志明著)学习笔记 通过一个类的全限定名来获取描述此类的二进制字节流的代码模块称为类加载器. 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在java虚拟机中的唯一性.通俗的理解:比较两个类是否"相等",只有在这两个类是同一类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载她们的类加载器不同,那这两个类必定不相等.这里的"相等",包括类的Class对象的equals()

对类加载器(ClassLoader)的理解

类加载器(ClassLoader) 当编辑器编译java源文件后,会产生以个相对一的字节码文件(.class) 当程序执行开始之前,必须将这个文件载入内存中,生成一个与之匹配的Class对象, 任何以个类加载之后jvm都会为其创建以个唯一的class对象(元对象),再后续都是通过这个Class对象来创建实例,后话(Class对象就是放射的基石.) 这个过程我们称之为类加载 要弄清楚类加载的机制,授信我们必须要清楚了解类加载的相关知识,它是完成整个类加载的重要工具. 简单的说,当有个Class文件