Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ClassLoader工作机制

ClassLoader工作机制

作者头像
MickyInvQ
发布于 2020-09-27 09:11:39
发布于 2020-09-27 09:11:39
42700
代码可运行
举报
文章被收录于专栏:InvQ的专栏InvQ的专栏
运行总次数:0
代码可运行

classLoader顾名思义就是类加载器。 负责将类加载到JVM中,它就好比开会时门口的接待员,负责给进入会场的嘉宾发放入证明,入会的嘉宾分为VIP会员,黄金会员,白金会员,和普通会员等。都赢的接待室也会分为VIP会员接待室,黄金会员接待室,白金会员接待室和普通会员接待室,不同等级的会员会被分到不同的接待室接待,所有的会员都想进入会场得有入会证明才行,一旦会员进入会场就会根据接待室的等级表示它们,也就是会员的身份由接待室决定。如果你是一位大佬但是你不是VIP接待室接待的,那么对不起,你仍然不是VIP会员。当然对你是不是VIP会有会有严格的审查规定,如果你是也不会冤枉你,但是如果你想还能进来那就另当别论了。 事实上,ClassLoader除了能将Class加载到JVM中之外,还有一个重要的作用就是审查每个类应该由谁加载,它是一种父优先的等级加载机制。ClassLoader除了上述两个作用外还有一个任务就是将Class字节码重新解析成JVM统一要求的对象格式。 所以,

ClassLoader的作用

  • 1.加载类
  • 2.审查每个类应该由谁加载
  • 3.将Class字节码重新解析成JVM统一要求的对象格式

ClassLoader类结构分析

首先ClassLoader是抽象类,下面罗列几个常用的 该类的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   protected final Class<?> defineClass(String name, byte[] b, int off, int len)
        throws ClassFormatError
  • defineClass方法,用于将byte字节流解析为JVM能够识别的Class对象,有了这个方法意味着我们不仅仅可以通过class文件实例化对象,还可以通过其他方式实例化对象,如我们通过网络接受到一个类的字节码,那这个字节码流直接创建类的class对象形式实例化对象。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected Class<?> findClass(String name) throws ClassNotFoundException 

findClass方法通常是和defineClass方式一起使用的,我们通过直接覆盖ClassLoader的findClass方法来实现类的加载规则,从而取得加载类的字节码,然后通过defineClass方法生成类的Class对象。 如果你不想重新定义加载类的规则,也没有复杂的处理逻辑,只想在运行时能够加载自己指定的一个类,那么你可以用 this.getClass().getClassLoader().loadClass("class")调用ClassLoader的loadClass方法获取这个类的Class对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public Class<?> loadClass(String name) throws ClassNotFoundException
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected final void resolveClass(Class<?> c) 

ClassLoader还有很多子类,我们如果要实现自己的ClassLoader,一般都会继承URLClassLoader这个子类,因为这个类已经帮我们实现了大部分工作,我们只需要在适当的地方修改就好了,就像我们要实现servlet时通常会直接继承HttpServlet一样。

ClassLoader的等级加载机制

在前面的会员进入会场的规则中,如何保证不同等级的会员通过不同的会员接待室进入会场呢? 因为有些会员自己并不能正确地找到接待自己的接待室,也有可能有些会员会冒充更高阶的会员身份混进去,所以必须要有机制能够保证所有会员都被正确的接待室接待进入会场,而且一个会员只能别一个接待室接待,不能出现两个接待室重复接待的情况,也就是不能同时拿到两个入场的证明,从而保证接待的一致性。如何设计这个接待规则呢?

ClassLoader就设计了这样一种接待机制,这个机制就是上级委托接待机制。 它是这样的: 任何一个会员到达任何一个会员接待室时,这个接待室首先会检查这个会员是否已经被自己接待过,如果已经接待过,则拒绝本次接待,也就是不再发入会证明了,如果没有接待过,那么会向上询问这个会员是否应该在上一级的更高级别的接待室接待,上级接待室会根据它们的接地规则,检查这个会员是否已经被接待过,如果已经接待过,同样的处理方法,将已经接待的结果反馈给下一级,如果也没有接待过,再向更高一级(如果有更高一级的话)接待室转发接待请求,更高一级也是同样的处理方法,直到有一级接待室接待或者告诉它下一级这个会员不是自己接待的结果,并且也不应该由他们接待,这个接待室将会正式接待这个会员,并发个它入会证明,这个会员就被定位为这个接待室等级的会员。

这种接待规则看上去有点麻烦,但是它却能保证所有的会员都被正确的接待室接待,会员的身份也不会错。也不存在冒充身份的会员。

这个JVM平台提供三层ClassLoader,这三层ClassLoader可以分为两种类型,可以理解为接待室服务的接待室和为会员服务的接待室。

(1)BootStrap ClassLoader

这个ClassLoader就是接待室服务自身的,它主要加载JVM自身工作需要的类。这个ClassLoader完全是由JVM自己控制的,需要加载哪个类,怎么加载都由JVM自己控制,别人也访问不到这个类,所以这儿ClassLoader是不遵守前面介绍的加载机制的,它仅仅是一个类的加载工具而已,既没有更高以及的父加载器,也没有子加载器。

(2)ExtClassLoader

这个类加载有点特殊,它是JVM自身的一部分,但是它的血统也不是很纯正,它并不是JVM亲自实现的,我们可以理解为这个类加载器是那些与这个大会合作的单位员工会员,这些会员既不是JVM内部的,也和普通的外部会员不同,所以就有这个类加载器来加载。它服务的特定目标在 System.getProperty("java.ext.dirs"); sysout出来后为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext

我们打开目录看下,

(3)AppClassLoader

这个类加载器就是专门为接待会员服务的,它的父类是ExtClassLoader。它服务的目标是广大普通会员,所有在 System.getProperty("java.class.path")目录下的类都可以被这个类加载,这个目录就是我们经常用到的classpath sysout后:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
E:\workspace\Test\bin;C:\Program Files\Java\jdk1.8.0_111\jre\lib\charsets.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\access-
bridge-64.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\cldrdata.jar;C:\Program 

Files\Java\jdk1.8.0_111\jre\lib\ext\dnsns.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\jfxrt.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\localedata.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\nashorn.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\sunec.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\sunjce_provider.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\sunmscapi.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\sunpkcs11.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\ext\zipfs.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\javaws.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\jce.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\jfr.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\jfxswt.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\management-
agent.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\plugin.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\resources.jar;C:\Program 
Files\Java\jdk1.8.0_111\jre\lib\rt.jar;D:\IntelliJ IDEA Community Edition 2017.3\lib\idea_rt.jar

如果我们要实现自己的类加载器,不管你是直接实现抽象类ClassLoader,还是继承URLClassLoader,或者其他子类,它的父类加载器都是AppClassLoader,因为不管调用那个父类构造器,创建的对象都必须最终调用ClassLoader.getSystemClassLoader()作为父加载器。而ClassLoader.getSystemClassLoader()方法获取到的正是AppClassLoader。 通常一个类加载器的等级结构如下所示:

ExtClassLoader和AppClassLoader都位于sun.misc.Launcher类中,它们都是Launcher的内部类

ExtClassLoader和AppClassLoader都继承了URLClassLoader类,而URLClassLoader又实现了抽象类ClassLoader,在创建Launcher 对象时,首先会创建ExtClassLoader,然后将ExtClassLoader对象作为父加载器创建AppClassLoader对象,而通过Launcher.getClassLoader()方法获取的ClassLoader就是AppClassLoader对象。所以,如果在java应用中没有定义其他ClassLoader,那么除了 System.getProperty("java.ext.dirs");目录下的类都是由ExtClassLoader加载外,其他类都是由AppClassLoader来加载

JVM加载Class文件到内存中有两种方式

  • 隐式加载:所谓隐式加载就是不通过在代码里调用ClassLoader来加载需要的类,而是通过JVM来自动加载需要的类到内存中的方式。例如,当我们在类中继承或者引用某个类时,JVM在解析当前这个类时发现引用的类不在内存中,那么就会自动将这些类加载到内存中。
  • 显示加载:相反的显示加载就是我们在代码中通过调用ClassLoader类来加载一个类的方式,例如,调用this.getClass().getClassLoader().loadClass(); 或者 Class.forName() 或者我们自己实现的ClassLoader的findClass方法等。

其实,这两种方式时混合使用的,例如,我们通过自定义的ClassLoader显示加载一个类时,这个类中有引用了其他类,那么这些类就是隐式加载到。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/04/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JVM-白话聊一聊JVM类加载和双亲委派机制源码解析
其中最核心的方法 loadClass ,其实现我们常说的双亲委派机制 ,我们后面展开。
小小工匠
2021/08/17
2910
ClassLoader解析(一):Java中的ClassLoader
Step1::自定义类加载器首先从缓存中查找Class是否已经加载,如果已将加载就返回该Class;如果没加载,则委托给父加载器也就是App ClassLoader。
用户1205080
2019/01/23
6250
从JDK源码级别彻底刨析JVM类加载机制
“ 当我们用java命令运行某个类的main函数启动程序时,大家有没有想过是怎样加载的,本文将带着大家一起探讨JVM类的加载机制”
会呼吸的Coder
2022/06/13
2910
从JDK源码级别彻底刨析JVM类加载机制
深入分析Java ClassLoader原理
大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的,则会引发系统异常。而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需要,通过Java的类加载机制(ClassLoader)来动态加载某个class文件到内存当中的,从而只有class文件被载入到了内存之后,才能被其它class所引用。所以ClassLoader就是用来动态加载class文件到内存当中用的。
哲洛不闹
2018/09/19
7530
深入分析Java ClassLoader原理
一看你就懂,超详细java中的ClassLoader详解
ClassLoader翻译过来就是类加载器,普通的java开发者其实用到的不多,但对于某些框架开发者来说却非常常见。理解ClassLoader的加载机制,也有利于我们编写出更高效的代码。ClassLoader的具体作用就是将class文件加载到jvm虚拟机中去,程序就可以正确运行了。但是,jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载。想想也是的,一次性加载那么多jar包那么多class,那内存不崩溃。本文的目的也是学习ClassLoader这种加载机制。
Frank909
2019/01/14
5.6K1
深入浅出Java的类加载机制使用自己的类别载入器
Java只有当需要使用类的时候,才会将类载入。java类的载入,是通过类加载器进行的。
desperate633
2018/08/22
7760
深入浅出Java的类加载机制使用自己的类别载入器
4. JDK源码级别彻底剖析类加载机制
当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到 JVM。
源码之路
2021/03/02
4430
4. JDK源码级别彻底剖析类加载机制
ClassLoader解惑
一个Java程序要想运行起来,首先需要经过编译生成 .class文件,然后创建一个运行环境(jvm)来加载字节码文件到内存运行,而.class 文件是怎样被加载中jvm 中的就是Java Classloader所做的事情。
加多
2018/09/06
1.5K0
ClassLoader解惑
深入理解Java类加载器(ClassLoader)
JVM重要的一个领域,类加载 当程序主动使用某个类时,如果该类还没被加载到内存中,则JVM就会通过加载,连接,初始化三个步骤来对类进行初始化,如果没有意外,JVM将会连续完成三个步骤,所以有时也把这个三个步骤称为类的初始化或类加载。
张哥编程
2024/12/13
5050
深入理解Java类加载器(ClassLoader)
2.双亲委派机制详细解析及原理
研究类加载的过程就是要知道类加载的时候使用了双亲委派机制。但仅仅知道双亲委派机制不是目的,目的是要了解为什么要使用双亲委派机制,他的原理是什么?知道双亲委派机制的逻辑思想,然后这个思想是否可以被我们借鉴,为我所用。这才是学习知识的目的。
用户7798898
2021/10/09
7380
话说 类加载过程 第一篇
用getClassLoader获取类加载器 如果是Null 那就是到了BootStrap类加载器 了 因为是C++实现的 木有对应类
木子的昼夜
2021/03/11
4940
话说 类加载过程 第一篇
JVM学习---类加载子系统
使用 BinaryViewer软件查看字节码文件,其开头均为 CAFE BABE ,如果出现不合法的字节码文件,那么将会验证不通过。
大忽悠爱学习
2021/11/15
2640
Android解析ClassLoader(一)Java中的ClassLoader
前言 热修复和插件化是目前比较热门的技术,要想更好的掌握它们需要了解ClassLoader,因此也就有了本系列的产生,这一篇我们先来学习Java中的ClassLoader。 1.ClassLoader的类型 在Java虚拟机(一)结构原理与运行时数据区域这篇文章中,我提到过类加载子系统,它的主要作用就是通过多种类加载器(ClassLoader)来查找和加载Class文件到 Java 虚拟机中。 Java中的类加载器主要有两种类型,系统类加载和自定义类加载器。其中系统类加载器包括3种,分别是Bootstra
用户1269200
2018/02/01
1.4K0
Android解析ClassLoader(一)Java中的ClassLoader
深入理解Java类加载器(1):Java类加载原理解析
  每个开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载。Java的类加载机制是技术体系中比较核心的部分,虽然和大部分开发人员直接打交道不多,但是对其背后的机理有一定理解有助于排查程序中出现的类加载失败等技术问题,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助。
全栈程序员站长
2022/09/22
9060
深入理解Java类加载器(1):Java类加载原理解析
ClassLoader究竟为何物?
要深入了解ClassLoader,首先就要知道ClassLoader是用来干什么的,顾名思义,它就是用来加载Class文件到JVM,以供程序使用 的。我们知道,java程序可以动态加载类定义,而这个动态加载的机制就是通过ClassLoader来实现的,所以可想而知ClassLoader的重 要性如何。 既然ClassLoader是用来加载类到JVM中的,那么ClassLoader又是如何被加载呢?难道它不是java的类? JDK 默认提供了如下几种ClassLoader: 1.  Bootstrp load
老白
2018/03/19
6580
由浅入深谈 Java 的类加载机制
本文涉及知识点:双亲委托机制、BootstrapClassLoader、ExtClassLoader、AppClassLoader等。 什么是 Java 类加载机制? Java 虚拟机使用 Java
神秘的寇先森
2018/05/30
5710
[Java类加载器]Java中classLoader浅析.
本文为在公司内部TD上写的一篇小文, 主要讲解java中classLoader基础知识, 现在拿来这里分享一下.  一、问题 请在Eclipse中新建如下类,并运行它: 1 package java.lang; 2 3 public class Long { 4 public static void main(String[] args) { 5 System.out.println("Hi, i am here"); 6 } 7 } 你能猜到它的运行如果吗? 不错,就是如
一枝花算不算浪漫
2018/05/18
1.4K0
类加载器详解
内容:转自 java知音 类加载器是负责将可能是网络上、也可能是磁盘上的class文件加载到内存中。并为其生成对应的java.lang.class对象。一旦一个类被载入JVM了,同一个类就不会被再次加载。 那么怎样才算是同一个类?在JAVA中一个类用其全限定类名(包名和类名)作为其唯一标识,但是在JVM中,一个类用其全限定类名和其类加载器作为其唯一标识。也就是说,在JAVA中的同一个类,如果用不同的类加载器加载,则生成的class对象认为是不同的。 当JVM启动时,会形成由三个类加载器组成的初始类加载器层
用户1257393
2018/01/30
7480
类加载器详解
Java 类加载器 ClassLoader 详解与双亲委托模型
jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载。 你想啊,假如一次性全部加载项目中的所有的 jar 包,那么多class,那内存还不崩溃?
一个会写诗的程序员
2021/02/04
1.4K0
JVM:第一章:类加载机制深度解析
加载 ----> 验证 ----> 准备 ----> 解析 ----> 初始化 ----> 使用 ----> 卸载
Java廖志伟
2021/02/02
7580
JVM:第一章:类加载机制深度解析
相关推荐
JVM-白话聊一聊JVM类加载和双亲委派机制源码解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验