本篇文章主要是详细写一下个人对Java ClassLoader的理解。

首先回顾一下,java虚拟机载入java类的步骤:java文件经过编译器编译后变成字节码文件(.class文件),类加载器(ClassLoader)读取.class文件,并且转换成java.lang.Class的一个实例,最后通过newInstance方法创建该类的一个对象。ClassLoader的作用就是根据一个类名,找到对应的字节码,根据这些字节码定义出对应的类,该类就是java.lang.Class的一个实例。

类加载器的组织结构

java有三个初始类加载器,当java虚拟机启动时,它们会按照以下顺序启动:Bootstrap classloader -> extension classloader -> system classloader。三者的关系:bootstrap classloader是extension classloader的parent,extension classloader是system classloader的parent。

bootstrap classloader

它是最原始的类加载器,并不是由java代码写的,是由原生代码编写的。Java有一次编译、所有平台运行的效果,就是因为它写了一份功能相同,但针对不同平台不同语言实现的底层代码。它负责加载java核心库,大家可运行以下代码,看看自己本地的java核心库在哪里:

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

本人的运行结果:

file:/home/eric/jdk1.6.0_35/jre/lib/resources.jar
file:/home/eric/jdk1.6.0_35/jre/lib/rt.jar
file:/home/eric/jdk1.6.0_35/jre/lib/sunrsasign.jar
file:/home/eric/jdk1.6.0_35/jre/lib/jsse.jar
file:/home/eric/jdk1.6.0_35/jre/lib/jce.jar
file:/home/eric/jdk1.6.0_35/jre/lib/charsets.jar
file:/home/eric/jdk1.6.0_35/jre/lib/modules/jdk.boot.jar
file:/home/eric/jdk1.6.0_35/jre/classes

extension classloader

它用来加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或java.ext.dirs系统属性指定的)JAR的类包。注意,因为它是bootstrap classloader加载的,所以当你运行:

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

输出的是:the parent of extension classloader : null

system classloader

它用于加载classpath目录下的jar包,我们写的java类,一般都是由它加载,除非你自己制定个人的类加载器。

全盘负责委托机制

classloader加载类时,使用全盘负责委托机制,可以分开两部分理解:全盘负责,委托。

全盘负责机制:若类A调用了类B,则类B和类B所引入的所有jar包,都由类A的类加载器统一加载。

委托机制:类加载器在加载类A时,会优先让父加载器加载,当父加载器加载不到,再找父父加载器,一直找到bootstrap  classloader都找不到,才自己去相关的路径去寻找加载。以下是ClassLoader的源码:

protected synchronized Class<?> loadClass(String name, boolean resolve)
	throws ClassNotFoundException
    {
	// First, check if the class has already been loaded
	Class c = findLoadedClass(name);
	if (c == null) {
	    try {
		if (parent != null) {
		    //从父加载器加载
		    c = parent.loadClass(name, false);
		} else {
		    //从bootstrap loader加载
		    c = findBootstrapClassOrNull(name);
		}
	    } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }
            if (c == null) {
	        // If still not found, then invoke findClass in order
	        // to find the class.
	        c = findClass(name);
	    }
	}
	if (resolve) {
	    resolveClass(c);
	}
	return c;
    }

举个例子,类加载器加载类A的过程:

1,判断是否已经加载过,在cache里面查找,若有,跳7;否则下一步

2,判断当前加载器是否有父加载器,若无,则当前为ext classloader,跳去4;否则下一步

3,请求父加载器加载该类,若加载成功,跳7;若不成功,即父加载器不能找到该类,跳2

4,请求jvm的bootstrap classloader加载,若加载成功,跳7;若失败,跳5

5,当前加载器自己加载,若成功,跳7;否则,跳6

6,抛出ClassNotFoundException

7,返回Class

编写自己的类加载器

Java加载类的过程,实质上是调用loadClass()方法,loadClass中调用findLoadedClass()方法来检查该类是否已经被加载过,如果没有就会调用父加载器的loadClass(),如果父加载器无法加载该类,就调用findClass()来查找该类。

所以我们要做的就是新建MyClassLoader继承java.lang.ClassLoader,重写其中的findClass()方法。主要是重新设计查找字节码文件的方案,然后调用definedClass来返回。

本人写了一个demo,用自己的类加载器去加载指定java文件,且带有热部署效果,具体请查看以下url。

Java类加载器深入理解的更多相关文章

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

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

  2. 深入理解Java类加载器(ClassLoader)

    深入理解Java类加载器(ClassLoader) Java学习记录--委派模型与类加载器 关于Java类加载双亲委派机制的思考(附一道面试题) 真正理解线程上下文类加载器(多案例分析) [jvm解析 ...

  3. 深入理解Java类加载器(ClassLoader) (转)

    转自: http://blog.csdn.net/javazejian/article/details/73413292 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Ja ...

  4. 深入理解:java类加载器

    概念理解:Java类加载器总结 1.深入理解Java类加载器(1):Java类加载原理解析 2.深入理解Java类加载器(2):线程上下文类加载器

  5. 深入理解Java类加载器(一):Java类加载原理解析

    摘要: 每个开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这个异常背后涉及到的是Java技术体系中的类加载机制.本文简述了JVM三种预定义类加载器,即 ...

  6. 深入理解Java类加载器(二):线程上下文类加载器

    摘要: 博文<深入理解Java类加载器(一):Java类加载原理解析>提到的类加载器的双亲委派模型并不是一个强制性的约束模型,而是Java设计者推荐给开发者的类加载器的实现方式.在Java ...

  7. 深入探讨 Java 类加载器

    转自:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器(class loader)是 Java™中的一个很重要的概念.类 ...

  8. 深入探讨 Java 类加载器[转]

    原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html 类加载器(class loader)是 Java™ ...

  9. 转载:深入探讨 Java 类加载器

    转载地址 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 深入探讨 Java 类加载器 类加载器(class loader) ...

随机推荐

  1. 如何解决eclipse上的Android程序“Please ensure that adb is correctly located at 'D:\eclipse\sdk\platform-tools\adb.exe' and can be executed.”小问题?

    首先,把运行的Android模拟器和eclipse一块儿关了, 然后win+R,cmd, 下面输入adb kill_server 再输入adb start_server 之后重新运行项目,不出意外的话 ...

  2. Camera类

    Camera类 使用 Camera 类可从连接到运行 Flash Player 的计算机的摄像头中 捕获视频. 使用 Video 类可在本地监视视频. 使用 NetConnection  和 NetS ...

  3. C#学习第五天

    字符串的处理 string可作char的只读数组 下面这段字符表示访问每个字符: string myString="A string."; char myChar=myString ...

  4. 【开源java游戏框架libgdx专题】-07-文件处理

    介绍:文件处理在不同平台的文件管理是略有差异的 Desktop(Windows,Linux,Mac OS X等等):在桌面系统中,文件系统是一个大块的内存.文件可以通过当前的工作目录或者绝对路径被引用 ...

  5. MySQL存储过程的基本函数(三)

    (1).字符串类 首先定义一个字符串变量:set @str="lxl"; CHARSET(str) //返回字串字符集 select charset(@str);+-------- ...

  6. PC端手机访问跳转手机站点

    第一种: var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.sr ...

  7. 免写前缀JS包--prefixfree.min.js--插件

    /** * StyleFix 1.0.3 & PrefixFree 1.0.7 * @author Lea Verou * MIT license */ (function(){functio ...

  8. HTML5 File 对象

    实例说明1: <div class="container"> <input type="file" id="file" m ...

  9. xmlns:android="http://schemas.android.com/apk/res/android" 是什么意思?

    声明xml命名空间.xmlns意思为“xml namespace”.冒号后面是给这个引用起的别名.schemas是xml文档的两种约束文件其中的一种,规定了xml中有哪些元素(标签).元素有哪些属性及 ...

  10. IDEA中Maven管理下添加mysql依赖

    在做Java Web项目的时候,不可避免的就要使用到数据库,下面就是在IDEA中添加mysql依赖的方法. 如果你看到这里,就表示你弄懂了IDEA,maven和Tomcat等,所以... 只需要在po ...