`

【转】理解Java ClassLoader机制

阅读更多
当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初始类加载器层次结构:
bootstrap classloader
|
extension classloader
|
system classloader

bootstrap classloader -引导(也称为原始)类加载器,它负责加载Java的核心类。在Sun的JVM中,在执行java的命令中使用-Xbootclasspath选项或使用 - D选项指定sun.boot.class.path系统属性值可以指定附加的类。这个加载器的是非常特殊的,它实际上不是 java.lang.ClassLoader的子类,而是由JVM自身实现的。大家可以通过执行以下代码来获得bootstrap classloader加载了那些核心类库:

URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls.toExternalform());
}


extension classloader -扩展类加载器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的)中JAR的类包。这为引入除Java核心类以外的新功能提供了一个标准机制。因为默认的扩展目录对所有从同一个JRE中启动的JVM都是通用的,所以放入这个目录的 JAR类包对所有的JVM和system classloader都是可见的。在这个实例上调用方法getParent()总是返回空值null,因为引导加载器bootstrap classloader不是一个真正的ClassLoader实例。所以当大家执行以下代码时:

System.out.println(System.getProperty("java.ext.dirs"));
ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();
System.out.println("the parent of extension classloader : "+extensionClassloader.getParent());


结果为:
C:\j2sdk1.4.1_01\jre\lib\ext
the parent of extension classloader : null
extension classloader是system classloader的parent,而bootstrap classloader是extension classloader的parent,但它不是一个实际的classloader,所以为null。

system classloader -系统(也称为应用)类加载器,它负责在JVM被启动时,加载来自在命令java中的-classpath或者java.class.path系统属性或者 CLASSPATH操作系统属性所指定的JAR类包和类路径。总能通过静态方法ClassLoader.getSystemClassLoader()找到该类加载器。如果没有特别指定,则用户自定义的任何类加载器都将该类加载器作为它的父加载器。执行以下代码即可获得:

System.out.println(System.getProperty("java.class.path"));


输出结果则为用户在系统属性里面设置的CLASSPATH。
classloader 加载类用的是全盘负责委托机制。所谓全盘负责,即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入;委托机制则是先让parent(父)类加载器 (而不是super,它与parent classloader类不是继承关系)寻找,只有在parent找不到的时候才从自己的类路径中去寻找。此外类加载还采用了cache机制,也就是如果 cache中保存了这个Class就直接返回它,如果没有才从文件中读取和转换成Class,并存入cache,这就是为什么我们修改了Class但是必须重新启动JVM才能生效的原因。

类加载器的顺序是:
先是bootstrap classloader,然后是extension classloader,最后才是system classloader。大家会发现加载的Class越是重要的越在靠前面。这样做的原因是出于安全性的考虑,试想如果system classloader“亲自”加载了一个具有破坏性的“java.lang.System”类的后果吧。这种委托机制保证了用户即使具有一个这样的类,也把它加入到了类路径中,但是它永远不会被载入,因为这个类总是由bootstrap classloader来加载的。大家可以执行一下以下的代码:
System.out.println(System.class.getClassLoader());


将会看到结果是null,这就表明java.lang.System是由bootstrap classloader加载的,因为bootstrap classloader不是一个真正的ClassLoader实例,而是由JVM实现的,正如前面已经说过的。

下面就让我们来看看JVM是如何来为我们来建立类加载器的结构的:
sun.misc.Launcher,顾名思义,当你执行java命令的时候,JVM会先使用bootstrap classloader载入并初始化一个Launcher,执行下来代码:

System.out.println("the Launcher's classloader is "+sun.misc.Launcher.getLauncher().getClass().getClassLoader());


结果为:
the Launcher's classloader is null (因为是用bootstrap classloader加载,所以class loader为null)
Launcher 会根据系统和命令设定初始化好class loader结构,JVM就用它来获得extension classloader和system classloader,并载入所有的需要载入的Class,最后执行java命令指定的带有静态的main方法的Class。extension classloader实际上是sun.misc.Launcher$ExtClassLoader类的一个实例,system classloader实际上是sun.misc.Launcher$AppClassLoader类的一个实例。并且都是 java.net.URLClassLoader的子类。

让我们来看看Launcher初试化的过程的部分代码。

Launcher的部分代码:
public class Launcher {
public Launcher() {
ExtClassLoader extclassloader;
try {
//初始化extension classloader
extclassloader = ExtClassLoader.getExtClassLoader();
} catch(IOException ioexception) {
throw new InternalError("Could not create extension class loader");
}
try {
//初始化system classloader,parent是extension classloader
loader = AppClassLoader.getAppClassLoader(extclassloader);
} catch(IOException ioexception1) {
throw new InternalError("Could not create application class loader");
}
//将system classloader设置成当前线程的context classloader(将在后面加以介绍)
Thread.currentThread().setContextClassLoader(loader);
......
}
public ClassLoader getClassLoader() {
//返回system classloader
return loader;
}
}


extension classloader的部分代码:
static class Launcher$ExtClassLoader extends URLClassLoader {

public static Launcher$ExtClassLoader getExtClassLoader()
throws IOException
{
File afile[] = getExtDirs();
return (Launcher$ExtClassLoader)AccessController.doPrivileged(new Launcher$1(afile));
}
private static File[] getExtDirs() {
//获得系统属性“java.ext.dirs”
String s = System.getProperty("java.ext.dirs");
File afile[];
if(s != null) {
StringTokenizer stringtokenizer = new StringTokenizer(s, File.pathSeparator);
int i = stringtokenizer.countTokens();
afile = new File;
for(int j = 0; j < i; j++)
afile[j] = new File(stringtokenizer.nextToken());

} else {
afile = new File[0];
}
return afile;
}
}


system classloader的部分代码:
static class Launcher$AppClassLoader extends URLClassLoader
{

public static ClassLoader getAppClassLoader(ClassLoader classloader)
throws IOException
{
//获得系统属性“java.class.path”
String s = System.getProperty("java.class.path");
File afile[] = s != null ? Launcher.access$200(s) : new File[0];
return (Launcher$AppClassLoader)AccessController.doPrivileged(new Launcher$2(s, afile, classloader));
}
}


转载地址:http://hi.baidu.com/hijiqimao/blog/item/574032ec141424d52e2e2122.html

分享到:
评论

相关推荐

    理解Java ClassLoader机制

    理解Java ClassLoader机制

    JAVA ClassLoader 讲解 (类加载器)

    ClassLoader类加载器讲解,理解JAVA类加载机制

    java的ClassLoader类加载器机制

    jvm运行的过程中,需要载入类,而类的加载需要类加载器,本文章提供了java的类加载器的工作原理。可以使读者更加理解jvm的运行机制。

    ClassLoader加载机制

    该电子书详细介绍了java虚拟机类加载机制,对于深入理解jvm工作原理有很好的帮助作用,对于初学java,有一定工作经验的小伙伴来说是一本提高自身java素养,夯实自己java基本技能的“葵花宝典”。

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ Java面试题79:redis数据淘汰机制.mp4 │ Java面试题80:java访问redis级redis集群?.mp4 │ Java面试题81:微信公众号分类和微信开发原理.mp4 │ Java面试题82:怎么把微信和业务平台进行绑定.mp4 │ Java面试题...

    12.尚硅谷_java基础_反射

    理解 Class 类 理解 Java 的类加载机制 学会使用 ClassLoader 进行类加载 理解反射的机制 掌握 Constructor、Method、Field 类的用法 理解并掌握动态代理

    尚硅谷_佟刚_Java基础_反射.pdf

    理解Class 类 理解Java 的类加载机制 学会使用ClassLoader 进行类加载 理解反射的机制 掌握Constructor、Method、Field 类的用法 理解并掌握动态代理

    Java高级工程师简历模板18k+

    3.对Java虚拟机、JMM、垃圾收集机制、GC算法、JVM常用配置参数、GC参数、classLoader、锁机制、JVM故障分析,jmap,jstack等jdk提供的工具命令,性能监控工具(java visualVM),JVM参数调优有一定了解; 4.熟悉java...

    Java 基础面试题

    该文档主要整理了常见的Java基础面试题,包含以下内容: 1. 抽象类和接口的区别 2. 什么时候使用抽象类,什么时候使用接口 ...34. 如何防止创建的类名不能java为已有类名,Java加载双亲委派机制 35. 堆和栈的区别

    基于JAVA的学生通讯录管理系统设计和实现[文献综述].doc

    除了Java语言具有的许多安全特性以外,Java对通过网络下载 的类具有一个安全防范机制(类ClassLoader),如分配不同的名字空间以防替代本地的 同名类、字节代码检查,并提供安全管理机制让Java应用设置安全哨兵。...

    深入分析Java Web技术内幕 修订版

    其次深入介绍了Java 技术,包括I/O 技术、中文编码问题、Javac 编译原理、class 文件结构解析、ClassLoader 工作机制及JVM 的内存管理等。最后介绍了Java 服务端技术,主要包括Servlet、Session 与Cookie、Tomcat 与...

    JavaSetup8u101.zip 编程工具

    除了Java 语言具有的许多安全特性以外,Java 对通过网络下载的类具有一个安全防范机制(类 ClassLoader),如分配不同的名字空间以防替代本地的同名类、字节代码检查,并提供安全管理机制(类 SecurityManager)让 ...

    Java虚拟机类装载:原理、实现与应用

    类的动态装载机制是JVM的一...本文介绍了JVM中类装载的原理、实现以及应用,尤其分析了ClassLoader的结构、用途以及如何利用自定义 的ClassLoader装载并执行Java类,希望能使读者对JVM中的类装载有一个比较深入的理解。

    全面解析Java类加载器

    深入理解和探究Java类加载机制—-  1.java.lang.ClassLoader类介绍  java.lang.ClassLoader类的基本职责是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java 类,即 ...

    基于Java的XML解析与反射设计模式.doc

    除了java语言具有的许多安全特性以外,java对通过网络下载的类具 有一个安全防范机制(类classloader),如分配不同的名字空间以防替代本地的同名类 、字节代码检查,并提供安全管理机制(类securitymanager)让java...

    Java编程经验

    学习Java比C++更容易理解OOP的思想,毕竟C++还混合了不少面向过程的成分。很多人都能背出来Java语言的特点,所谓的动态加载机制等等。当然概念往往是先记住而后消化的,可有多少人真正去体会过动态加载的机制,试图...

    Java经典入门教程pdf完整版

    五:Java如何做到让机器理解我们想要做的东西 用·个图来描述这个过程会比较谷易理解: PDF文件使用&quot; pdfFactory Pro&quot;试用版本创建ww, fineprint,cn Java私塾跟我学系列JAⅥ篇网址:htp:/www.lavass.Cn电话:...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【基础】java多态的理解 13 【基础】transient关键字 15 【基础】访问修饰符区别 15 【基础】java基本数据类型(四类八种) 15 Java自动类型转换 16 数据类型自动提升(注意以下讨论的是二元操作符) 16 【基础】...

Global site tag (gtag.js) - Google Analytics