类加载器双亲委派模型图 双亲委派模型构成 启动类加载器 扩展类加载器 应用程序类加载器 自定义类加载器 双亲委派模型工作过程是 如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成 为什么需要双亲委派模型? 如果没有双亲委派,那么用户是不是可以自己定义一个java.lang.Object的同名类、java.lang.String的同名类,等等,并把它放到ClassPath中,那么类之间的比较结果及类的唯一性将无法保证 因此,双亲委派模型可以防止内存中出现多份同样的字节码。
双亲委派机制 在加载类的时候,会一级一级向上委托,判断是否已经加载,从自定义类加载器-》应用类加载器-》扩展类加载器-》启动类加载器,如果到最后都没有加载这个类,则回去加载自己的类。 双亲委托有个弊端: 不能向下委派,不能不委派 怎么打破双亲委派机制:(也就是能向下委派和不委派) 自定义类加载器(不委派) spi机制(向下委派) 打破双亲委派 打破双亲委派的两种方式: 1.通过spi 由于双亲委派模型,父加载器是拿不到通过子加载器加载的类的。这个时候就需要启动类加载器来委托子类来加载Driver实现,从而破坏了双亲委派。 自定义类加载器 实现逻辑:自定义类继承classLoader,作为自定义类加载器,重写loadClass方法,不让它执行双亲委派逻辑,从而打破双亲委派。 jvm肯定解决了这个问题,openjdk源码在AccessController.doPrivileged 学名叫做沙箱安全机制,主要作用是:保护核心类,防止打破双亲委派机制,防篡改,如果重名的话就报异常
1.双亲委派机制原理 Java虚拟机对 class 文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的 class 文件加载到内存中生成 class 对象。 而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行 父类加载器一层一层往下分配任务,如果子类加载器能加载,则加载此类,如果将加载任务分配至系统类加载器也无法加载此类,则抛出异常 图片 2.双亲委派机制代码示例 举例一: 我们自己定义一个java.lang public static void main(String[] args) { System.out.println("hello,String"); } } 原因:由于双亲委派机制 3.双亲委派机制的优势 避免类的重复加载 保护程序安全,防止核心API被随意篡改 自定义类:java.lang.String 没有调用 自定义类:java.lang.ShkStart(报错:阻止创建
什么是打破双亲委派机制呢? 那么这里第一步, 我们需要知道什么是双亲委派机制? 前面已经说了什么是双亲委派机制了, 那打破是怎么回事呢? 根据双亲委派机制, 我们知道, 他一定是被应用程序类加载器AppClassLoader加载, 而不是我们自定义的类加载器, 为什么呢? 因为他要向上寻找, 向下委托. 我们要打破双亲委派机制, 就是要让自定义类加载器来加载我们的User1.class, 而不是应用程序类加载器来加载 接下来分析, 如何打破双亲委派机制呢? 双亲委派机制是在哪里实现的? 里面实现了双亲委派机制 下面给DefinedClassLoaderTest.java增加一个loadClass方法, 拷贝上面的代码即可. 删除掉中间实现双亲委派机制的部分 这里需要注意的是, com.lxl.jvm是自定义的类包, 只有我们自己定义的类才从这里加载. 如果是系统类, 依然使用双亲委派机制来加载.
网上有很多案例或者博客都相对的讲出了JVM的双亲委派机制,但是一上来就强调什么父子继承体系。 这个从语义上来说是这么个关系,但是从运行上来说却完全不是这么一回事。 双亲委派详细流程图 重点 父加载器不是“类加载器的父类加载器”!!! 双亲委派是一个孩子向父亲(上级)方向,然后父亲向孩子方向的双亲委派过程 为什么要用双亲委派?
双亲委派机制是Java中非常重要的类加载机制,它保证了类加载的完整性和安全性,避免了类的重复加载。 这篇文章就跟大家一起聊聊,Java中类加载的双亲委派机制到底是怎么回事,有哪些破坏双亲委派机制的案例,为什么要破坏双亲委派机制,希望对你会有所帮助。 1 为什么要双亲委派机制? 为了解决上面的这一系列的问题,我们必须要引入某一套机制,这套机制就是:双亲委派机制。 2 什么是双亲委派机制? 接下来,我们看看什么是双亲委派机制。 3 破坏双亲委派机制的场景 既然Java中引入了双亲委派机制,为什么要破坏它呢? 答:因为它有一些缺点。 下面给大家列举一下,破坏双亲委派机制最常见的场景。 这些原因导致,Tomcat没有办法使用传统的双亲委派机制加载类了。 那么,Tomcat加载类的机制是怎么样的?
上文:jdk-Launcher源码学习 ---- 背景 上文说过,jdk是通过双亲委派机制实现类的加载,但是这个加载效率及场景存在弊端,所以本文借鉴tomcat的实现方式去打破双亲委派机制实现自定义类加载器来模似 java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author hong * @version 1.0 * @description: 模似打破双亲委派机制 com.classloader.simulate.SimulateTomcatClassLoader$MySelfClassLoader 最后 很多容器都是打破Jvm的双亲委派机制来实现的,比如 tomcat,如果不打破的话根据无法部署多个项目,所以打破双亲委派机制也是一种业务场景的需要。 而通过了解和实现打破双亲委派机制来学习tomcat的实现,有效提升对jvm底层的实现了解。
类的生命周期 类加载器 双亲委派机制 类的生命周期 类从被加载到虚拟机开始,到卸载出内存为止,它的整个的生命周期包括:加载、连接(验证、准备、解析)、初始化、使用和卸载七个阶段。 类加载的双亲委派模型并不是强制的,用户可以根据需要在某个时间点动态加载类 扩展类加载源,例如从数据库、网络进行类加载 防止源代码泄露。 Java代码很容易被反编译和篡改,为了防止源码泄露,可以对类的字节码文件进行加密,并编写自定义的类加载器来加载自己的应用程序的类 双亲委派机制 向上委托,向下加载 如果一个类加载器收到了类加载的请求 c = findClass(name); } } return c; } 双亲委派机制的作用 1、避免类的重复加载。 参考: 通俗易懂的双亲委派机制:https://blog.csdn.net/codeyanbao/article/details/82875064 Java 符号引用 与 直接引用:https://www.cnblogs.com
双亲委派模型 模型如下图: 双亲委派模型中除了启动类加载器之外其余都需要有自己的父类加载器 当一个类收到了类加载请求时: 自己不会首先加载,而是委派给父加载器进行加载,每个层次的加载器都是这样。 双亲委派的好处 : 由于每个类加载都会经过最顶层的启动类加载器,比如 java.lang.Object这样的类在各个类加载器下都是同一个类(只有当两个类是由同一个类加载器加载的才有意义,这两个类才相等。 如果没有双亲委派模型,由各个类加载器自行加载的话。
双亲委派机制 Parent Delegation Model,又称为父级委托模型。想要了解它,还需理解类加载机制、类加载器、类加载器的层级关系。 双亲委派机制,是按照加载器的层级关系,逐层进行委派。 要加载一个类MyClass.class,从低层级到高层级一级一级委派,先由应用层加载器委派给扩展类加载器,再由扩展类委派给启动类加载器;启动类加载器载入失败,再由扩展类加载器载入,扩展类加载器载入失败, 双亲委派机制的优点: 1.保证安全性,层级关系代表优先级,也就是所有类的加载,优先给启动类加载器,这样就保证了核心类库类。 2.避免重复,如果父类加载器加载过了,子类加载器就没有必要再去加载了。 双亲委派机制 双亲委派机制指,当某个特定的类加载器在收到类加载的请求时,会遵循下面的规则顺序: 先判断被加载的类是否加载过,如果是则结束,否则会将加载任务委托给自己的父亲; 父类加载器在收到类加载的请求时
一、双亲(父亲)委派机制 java中存在3种类型的类加载器:引导类加载器,扩展类加载器和系统类加载器。三者是的关系是:引导类加载器是扩展类加载器的父类,扩展类加载器是系统类加载器的父类。 需要注意的是,Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象,而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式即把请求交由父类处理 但是,我们可以自己定义一个类加载器来达到这个目的,为了避免双亲委托机制,这个类加载器也必须是特殊的。 ------------------------------------------------------------------------------------------------ 什么是双亲委派机制 image.png 双亲委派机制的作用 1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。 2、保证核心.class不能被篡改。
(可自行思考一下,具体内容细节暂时不做扩展) 类加载器 终于来到了本文的主题 —— 类加载器和双亲委派机制。 双亲委派机制 在介绍双亲委派机制之前,先观察一下以下代码能否正确运行: //自己定义的一个 java.lang包 package java.lang; public class String { 其实,问题的关键就在于类加载遵循双亲委派机制。 类加载器有以下这样的层次关系: ? 当一个类在加载的时候,都会先委派它的父加载器去加载,这样一层层的向上委派,直到最顶层的启动类加载器。 这就是类的双亲委派机制。 这样做有什么好处呢?这就相当于维护了一个有优先级的层级关系,即总是从最顶层的父加载器开始加载。 因为双亲委派机制的存在,去加载我们自己定义的“java.lang.String”类的时候,会最终委派到顶层的启动类加载器,然后找到了rt.jar包下的“java.lang.String”。
双亲委派机制是Java类加载器的一种基础架构,它的作用是保证Java中类的安全性和稳定性。 双亲委派机制的优点是保证了类的唯一性,避免了重复加载。 接下来我们将介绍如何破坏双亲委派机制。在默认情况下,系统自动采用双亲委派机制,如果我们想打破这个机制,只需要自己定义一个类加载器,并且在该类加载器中覆盖loadClass()方法即可。 那么为什么要破坏双亲委派机制呢? 此时,我们就需要破坏双亲委派机制,自定义类加载器来实现这个功能
文章内容引用自 咕泡科技 咕泡出品,必属精品 首先我们要知道双亲委派机制是为了解决什么问题? 双亲委派机制的目的: 为了安全,保证核心类库的安全性,防止被篡改,以及保证类的唯一 怎么保证类的唯一呢? 这个符合了我们最开始所说的类的加载过程中除了读取二进制流憎操作外,剩余的逻辑都是由jvm内部实现的,双亲委派机制就是这么简单。 打破双亲委派机制 在大部分情况下,双亲委派机制是能够生效并且是能按预期执行的。 1第一次被破坏 在一些情况下,双亲委派机制是可以主动破坏的,细心的同学可以发现,我自己通过匿名内部类直接重写了java.lang.classloader的load class方法,而我们的双亲委派机制是存在于这个方法内的
双亲委派机制 1.1 什么是双亲委派机制 我们先来看一个案例: package com.lxl.jvm; import sun.misc.Launcher; import java.net.URL; 这就是下面要说的双亲委派机制. ? 上面这个图就是双亲委派机制的图. 什么意思呢? 比如: 我现在有一个自定义的java.lxl.jvm.Math类. 已经有了, 就直接返回了. 1.2 源码分析双亲委派机制 我们来看一下类加载器.类加载器主要调用的是classLoader.loadClass("com.lxl.Math") 这个方法来实现双亲委派机制的 这就是双亲委派机制的源码. 那么当下一次在遇到com.lxl.jvm.Math类的时候, 我们在AppClassLoader中就已经有了, 直接就返回了. 在来看一遍双亲委派机制的流程图 ? 不可能, 因为自己定义的类根本不会被加载 这就是双亲委派机制的第一个作用: 沙箱安全机制, 自己写的java.lang.String.class类不会被加载, 这样便可以防止核心API库被随意修改 双亲委派机制还有一个好处
2、双亲委派机制 双亲委派模型的工作过程是:如果一个类加载器收到了类加载请求,它首先不会自己尝试加载这个类,而是把这个请求委派给父类加载器去完成,每个层都是如此,因此所有加载请求最终都传送给顶层的启动类加载器 ,只有父加载器反馈自己无法加载这个加载请求时(它的搜索范围没有找到所需的类),子加载器才会尝试自己去完成加载,双亲委派机制说简单点就是,先找父亲加载,不行再由儿子自己加载 好处 具备优先级的层次关系 System.out.println("Object"); } } 结果 2.1、ClassLoader源码 AppClassLoader的继承关系 应用程序类加载器AppClassLoader加载类的双亲委派机制源码 会初始化父类ClassLoader,而ClassLoader的构造方法中,会给this.parent赋值,如下l.getClassLoader();中对应的类加载器就是AppClassLoader,满足双亲委派机制 4、打破双亲委派机制 例如在Tomact中部署多个项目,每个项目使用的相同但不用版本的组件 自定义类加载器,在加载类时,没有遵循双亲委派机制(先委托父加载器,父加载器没有此类,最后在交给子加载器加载
目录 一、前言 二、双亲委派 2.1、为什么需要双亲委派 2.2、双亲委派的实现 三、破坏双亲委派 3.1、为什么需要破坏双亲委派? 前段时间,笔者同事提出了一个关于类加载器破坏双亲委派的问题,以我们常见到的数据库驱动Driver为例,为什么要实现破坏双亲委派,下面一起来重温一下。 二、双亲委派 想要知道为什么要破坏双亲委派,就要先从什么是双亲委派说起,在此之前,我们先要了解一些概念: 对于任意一个类,都需要由加载它的类加载器和这个类本身来一同确立其在Java虚拟机中的唯一性。 3.1、为什么需要破坏双亲委派? 3.2、破坏双亲委派的实现 我们结合Driver来看一下在spi(Service Provider Inteface)中如何实现破坏双亲委派。
这时候,我们就提到了委派机制,那我们就得来看看这个双亲委派机制是什么了? 双亲委派机制 双亲委派机制(Parent Delegation Mechanism)是Java中类加载器(ClassLoader)的一种工作机制,旨在保证类的加载是有序的,避免重复加载同一个类,并确保类的安全性和一致性 需要注意的是,虽然双亲委派机制在大多数情况下是有益的,但在某些特殊的应用场景下,可能需要打破这种机制以实现自定义的类加载策略。 所以双亲委派机制在 JVM 中是十分重要的,如果没有双亲委派机制则会出现下面的这几种情况了: 1.安全性降低 Java的核心类库会被随意替换或篡改 2.类加载冲突 不同的类加载器可能会加载同一个类的不同版本 ,这会导致类加载冲突 3.类的加载顺序将变得不可预测 4.破坏JVM的模块化 所以,你对双亲委派机制了解了么?
别人就会羡慕你 呕心沥血半年之作,进去不点赞你回来骂我 https://blog.csdn.net/codeyanbao/article/details/111569150 你得先知道 在介绍双亲委派机制的时候 双亲委派机制 我打开了我的AndroidStudio,搜索了下“ClassLoader”,然后打开“java.lang”包下的ClassLoader类。 c = findClass(name); } } return c; } 其实这段代码已经很好的解释了双亲委派机制 为什么要设计这种机制 这种设计有个好处是,如果有人想替换系统级别的类:String.java。篡改它的实现,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了(为什么?
1.自定义加载器 沿用双亲委派机制自定义类加载器很简单,只需继承ClassLoader类并重写findClass方法即可。 object = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } } } 2.打破双亲委派机制则不仅要继承 ClassLoader的TestClassLoaderN类,这个类与前面的TestClassLoader类很相似,但它除了重写findClass方法外还重写了loadClass方法,默认的loadClass方法是实现了双亲委派机制的逻辑 这里为了破坏双亲委派机制必须重写loadClass方法,即这里先尝试交由System类加载器加载,加载失败才会由自己加载。它并没有优先交给父类加载器,这就打破了双亲委派机制。