当前位置:网站首页>clssloader与双亲委派
clssloader与双亲委派
2022-08-04 05:32:00 【real沛林】
JVM里的有几种classloader,为什么会有多种?
什么是双亲委派机制?介绍一些运作过程,双亲委派模型的好处;
什么情况下我们需要破坏双亲委派模型;
常见的JVM调优方法有哪些?可以具体到调整哪个参数,调成什么值?
https://blog.csdn.net/briblue/article/details/54973413
Java装载类使用“全盘负责委托机制”。“全盘负责”是指当一个ClassLoder装载一个类时,除非显示的使用另外一个ClassLoder,该类所依赖及引用的类也由这个ClassLoder载入;“委托机制”是指先委托父类装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类。这一点是从安全方面考虑的,试想如果一个人写了一个恶意的基础类(如java.lang.String)并加载到JVM将会引起严重的后果,但有了全盘负责制,java.lang.String永远是由根装载器来装载,避免以上情况发生 除了JVM默认的三个ClassLoder以外,第三方可以编写自己的类装载器,以实现一些特殊的需求。类文件被装载解析后,在JVM中都有一个对应的java.lang.Class对象,提供了类结构信息的描述。数组,枚举及基本数据类型,甚至void都拥有对应的Class对象。Class类没有public的构造方法,Class对象是在装载类时由JVM通过调用类装载器中的defineClass()方法自动构造的。
类加载
ClassLoader 顾名思义就是类加载器,ClassLoader 作用:
- 负责将 Class 加载到 JVM 中
- 审查每个类由谁加载(父优先的等级加载机制)
- 将 Class 字节码重新解析成 JVM统一要求的对象格式
什么情况下需要开始类加载过程的第一个阶段:”加载”。虚拟机规范中并没强行约束,这点可以交给虚拟机的的具体实现自由把握,但是对于初始化阶段虚拟机规范是严格规定了如下几种情况,如果类未初始化会对类进行初始化:
- 创建类的实例
- 对类进行反射调用的时候,如果累没有进行过初始化,则需要先触发其初始化
- 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
- 当虚拟机启动时,用户需要指定一个要执行的主类(包含main 方法的那个类),虚拟机会先初始化这个主类
- 当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。
其余的其他情况,称为被动引用,都不会触发类的初始化。下面也举了些被动引用的例子:
1.构造某个类的数组时并不会导致类的初始化,比如下面的例子:
public static void main(String[] args){
Simple[] simples = new Simple[10];
System.out.println(simples.length);
}
该操作只不过是在堆内存中开辟了一段连续的地址空间4byte x 10。
2.引用类的静态常量不会导致类的初始化
常量在编译阶段会存入调用类的常量池
3.jdk:1.8 通过子类引用父类的静态字段,不会导致子类初始化
class SuperClass{
static {
System.out.println("SuperClass init!");
}
public static int value=123;
}
class SubClass extends SuperClass{
static {
System.out.println("SubClass init!");
}
}
public class Test {
public static void main(String[] args)throws Exception{
System.out.println(SubClass.value);
//输出:
//SuperClass init!
//123
}
}
通过其子类来引用父类中定义的静态字段,只会触发父类初始化而不会触发子类的初始化。至于是否要触发子类的加载和验证,这个在虚拟机规范中并没有明确规定,这点取决于虚拟机的具体实现。
https://segmentfault.com/a/1190000013469223#articleHeader7
破坏双亲委派模型
双亲委派模型并不是一个强制性的约束模型,在java的世界中大部分的类加载器都遵循这个模型,但也有例外,一个典型的例子便是JNDI服务。
JNDI存放于rt.jar,由启动类加载器加载,JNDI的目的是对资源进行集中管理和查找,它需要调用由各厂商实现并部署在应用程序ClassPath下的JNDI接口实现的代码,如此一来,在双亲委派模型下,启动类加载器根本无法加载这些代码
针对此问题,java设计团队引入了线程上下文类加载器(Thread Context ClassLoader),这个类加载器可以通过Thread类的setContextClassLoader进行设置,默认继承父线程类加载器
通过线程上下文类加载器,JNDI服务通过此类加载器,由父类加载器请求子类加载器完成类加载动作
破坏双亲委派模型的例子还有很多,如tomcat服务、osgi、jigsaw等等,是否破坏双亲委派模型并没有对与错,只是不同场景下的具体应用而已
类的唯一性
对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间
边栏推荐
- LeetCode_Nov_5th_Week
- MNIST Handwritten Digit Recognition - Lenet-5's First Commercial Grade Convolutional Neural Network
- 基于Webrtc和Janus的多人视频会议系统开发5 - 发布媒体流到Janus服务器
- MVC自定义配置
- A code example of the PCL method in the domain of DG (Domain Generalization)
- LeetCode_Nov_2nd_Week
- 2022在 Go (Golang) 中使用微服务的系统课程
- Copy Siege Lion's Annual "Battle" | Review 2020
- 基于Webrtc和Janus的多人视频会议系统开发6 - 从Janus服务器订阅媒体流
- 【C语言】数组名是什么
猜你喜欢
随机推荐
[日常办公][ssh]cheatsheet
安装Apache服务时出现的几个问题, AH00369,AH00526,AH00072....
tmux概念和使用
理想的生活
How to get started with MOOSE platform - an example of how to run the official tutorial
MNIST handwritten digit recognition - based on Mindspore to quickly build a perceptron to achieve ten categories
第一章 绪论
树和二叉树
IDEA中创建web项目实现步骤
strlen 转义字符
webrtc代码解读一:音频数据的接收解码播放过程
安装MySQL的详细步骤
Fabric v1.1 环境搭建
Tensorflow/Pytorch安装(Anaconda环境下,无版本冲突,亲测有效)
虚幻引擎 5 完整指南[2022六月最新课程学习内容]
网络通信与Socket编程概述
counting cycle
SFTP的用法
MySQL基础
【C语言】数组名是什么