类加载机制
类的加载过程
加载过程可以分为3大阶段:加载 - 链接(验证 -准备 - 解析) - 初始化,如下图:
加载
这里的加载可以从字面意思理解,主要作用是将外部的 .class 文件转换为二进制数据并加载到JVM的方法区内 , 这里的外部可以指:jar、war、网络中等等
验证
校验 class 文件的格式对否满足JVM规范,不符合规范的将抛出 java.lang.VerifyError 错误
准备
为类变量分配内存,并将其初始化为默认值。此时,实例对象还没有分配内存,所以这些动作是在方法区上进行的。
类变量有两次赋初始值的过程,一次在准备阶段,赋予初始值(也可以是指定值);另外一次在初始化阶段,赋予程序员定义的值。因此,即使程序员没有为类变量赋值也没有关系,它仍然有一个默认的初始值。但局部变量就不一样了,如果没有给它赋初始值,是不能使用的。
解析
将符号引用替换为直接引用的过程,符号引用是一种定义,可以是任何字面上的含义,而直接引用就是直接指向目标的指针、相对偏移量 。 这个阶段大体可以分为:
- 类或接口的解析
- 类方法解析
- 接口方法解析
- 字段解析
我们经常发生的异常,就与这个阶段有关。
java.lang.NoSuchFieldError
根据继承关系从下往上,找不到相关字段时的报错。java.lang.IllegalAccessError
字段或者方法,访问权限不具备时的错误。java.lang.NoSuchMethodError
找不到相关方法时的错误。
解析过程保证了相互引用的完整性,把继承与组合推进到运行时
初始化
进行成员变量的初始化工作
类加载器
类加载器负责类的加载工作,安全、校验等工作都由它来负责。
Bootstrap ClassLoader
它的作用是加载核心类库,也就是 rt.jar、resources.jar、charsets.jar 等。当然这些 jar 包的路径是可以指定的,-Xbootclasspath 参数可以完成指定操作。这个加载器是 C++ 编写的,随着 JVM 启动
Extention ClassLoader
扩展类加载器,主要用于加载 lib/ext 目录下的 jar 包和 .class 文件。同样的,通过系统变量 java.ext.dirs 可以指定这个目录。这个加载器是个 Java 类,继承自 URLClassLoader
App ClassLoader
我们写的 Java 类的默认加载器,有时候也叫作 System ClassLoader。一般用来加载 classpath 下的其他所有 jar 包和 .class 文件,我们写的代码,会首先尝试使用这个类加载器进行加载
Custom ClassLoader
自定义加载器,支持一些个性化的扩展功能
双亲委派机制
在加载一个类的时候,无论子类是否有能力加载,都要先依托父类加载,如果父类没有能力加载那么子类才会加载,这种机制称为双亲委派机制,个人理解双亲就是指:bootstrap、extention classloader。好处是:保证一个类只会被加载一次、并且安全,想象一下如果Object存在于多个,程序会是什么样子。
打破双亲委派的案例
重写loadclass
方法即可打破双亲委派机制
Tomcat
Tomcat在加载webapp的时候为了保证多个app的隔离性,加载时是由子类优先加载的,加载不到才会交给父类加载
SPI
ServiceLoader.java 是属于bootstrap classloader 加载的类 , 如果按双清委派模型的话是不可能加载到三方jar中的类的。但是JDK玩了一个小技巧:把加载三方jar的类加载器设置为Thread.currentThread().getContextClassLoader()
d , 我们知道线程上下文类加载器默认为application classloader。
使用endorsed实现JDK类的替换
以下介绍两种方式来实现替换JDK的类,但是这两种方式都需要把自己写的java源文件打成jar包
方式一
使用虚拟机参数 -Djava.endorsed.dirs 指定你自己写的jar包所在目录,jar可以放在任何目录
方式二
把你自己打的jar包放在 %JAVA_HOME%\jre\lib\endorsed
下面,这个目录是固定的,无需再次指定虚拟机参数-Djava.endorsed.dirs
注意这里有坑,如果你在其他帖子中看到的可以替换java.lang.*
或者 java.util.*
下面的JDK类,那很有可能基于的JDK版本比较低,例如1.8以下 。 本人在1.8的JDK中以及不支持替换java.util.*
下面的类了,启动会报如下异常**
在JDK8中只支持替换一小部分的JDK类,参考JDK文档:https://docs.oracle.com/javase/8/docs/technotes/guides/standards/index.html#endorsed-standards-apis
多说一句:貌似在JDK9中已经把endorsed机制给删除了
本文来自博客园,作者:林一gg,转载请注明原文链接:https://www.cnblogs.com/linyigg/p/13291417.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端