关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »Java类加载器深入理解

    Java类加载器深入理解

    2016-01-13 00:00:00 出处:itjs.cn
    分享

    本篇文章主要是详细写一下个人对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。

    Demo地址:http://git.oschina.net/ericquan8/hot-deploy

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。