Java类加载器深入理解
本篇文章主要是详细写一下个人对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类加载器深入理解的更多相关文章
- java笔记--理解java类加载器以及ClassLoader类
类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...
- 深入理解Java类加载器(ClassLoader)
深入理解Java类加载器(ClassLoader) Java学习记录--委派模型与类加载器 关于Java类加载双亲委派机制的思考(附一道面试题) 真正理解线程上下文类加载器(多案例分析) [jvm解析 ...
- 深入理解Java类加载器(ClassLoader) (转)
转自: http://blog.csdn.net/javazejian/article/details/73413292 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Ja ...
- 深入理解:java类加载器
概念理解:Java类加载器总结 1.深入理解Java类加载器(1):Java类加载原理解析 2.深入理解Java类加载器(2):线程上下文类加载器
- 深入理解Java类加载器(一):Java类加载原理解析
摘要: 每个开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这个异常背后涉及到的是Java技术体系中的类加载机制.本文简述了JVM三种预定义类加载器,即 ...
- 深入理解Java类加载器(二):线程上下文类加载器
摘要: 博文<深入理解Java类加载器(一):Java类加载原理解析>提到的类加载器的双亲委派模型并不是一个强制性的约束模型,而是Java设计者推荐给开发者的类加载器的实现方式.在Java ...
- 深入探讨 Java 类加载器
转自:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器(class loader)是 Java™中的一个很重要的概念.类 ...
- 深入探讨 Java 类加载器[转]
原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html 类加载器(class loader)是 Java™ ...
- 转载:深入探讨 Java 类加载器
转载地址 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 深入探讨 Java 类加载器 类加载器(class loader) ...
随机推荐
- Android Xutils 框架
XUtils是git上比较活跃 功能比较完善的一个框架,是基于afinal开发的,比afinal稳定性提高了不少,下面是介绍: 鉴于大家的热情,我又写了一篇Android 最火框架XUtils之注解机 ...
- LinkButton和HyperLink的页面跳转用法
<%--<asp:HyperLink ID="HyperLink1" NavigateUrl='<%#"/Fxy_Admin/Pro_ClassNew. ...
- sql server identity限制
identity属性是依赖于表的,它不是一种独立的序列机制,不能随意使用它生成新值. 标识值是在insert语句执行时生成的,不是在执行之前生成的. identity属性是以异步的方式分配标识值.这意 ...
- [转载]C++中声明与定义的区别
C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...
- Spring4.0学习笔记(12) —— JDBCTemplate 操作数据库
整体配置 1.配置xml文件 <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi ...
- LoadRunner安装停在注册界面安装失败----解决办法之一
今天下了个LoadRunner11.5玩玩,准备测手头上准备发布的项目性能,结果安装的时候,报错“Error Creating system registry entry”,在51testing搜索各 ...
- 面向对象设计模式之Facade外观模式(结构型)
动机:有些系统组件的客户和组件中各种复杂的子系统有了过多的的耦合,随着外部客户程序 和个子系统的演化,这种过多的耦合面临很多变化的挑战:如何简化外部客户程序和系统的交互接口? 如何将外部客户程序的 ...
- 如何用angularjs制作一个完整的表格之四__自定义ng-model标签的属性使其支持input之外的html元素
有的时候我们需要为非input类型的元素添加ng-model来实现双向的数据绑定,从而减少冗余代码,那么可以尝试一下的方式 例如:我页面中使用了contenteditable这个属性来实现用户可直接编 ...
- 0627 CMD运行php代码
打开cmd: 如何在这里面运行php代码 1.调整环境变量:右击电脑->属性->高级系统设置->环境变量 2.新建环境变量: 上部分的用户变量----- 变量名:PHP_HOME ...
- frame与iframe的区别?
1.frame不能脱离frameSet单独使用,iframe可以 2.frame不能放在body中,否则不能正常显示 3.嵌套在frameSet中的iframe必需放在body中,不嵌套在frameS ...