关于Java类加载双亲委派机制的思考(附面试题)

转载自 关于Java类加载双亲委派机制的思考(附面试题)

 

预定义类加载器和双亲委派机制

  1. JVM预定义的三种类型类加载器:
  • 启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
  • 标准扩展(Extension)类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
  • 系统(System)类加载器:是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器。

除了以上列举的三种类加载器,还有一种比较特殊的类型 — 线程上下文类加载器。

  1. 双亲委派机制描述
    某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

几点思考

  1. Java虚拟机的第一个类加载器是Bootstrap,这个加载器很特殊,它不是Java类,因此它不需要被别人加载,它嵌套在Java虚拟机内核里面,也就是JVM启动的时候Bootstrap就已经启动,它是用C++写的二进制代码(不是字节码),它可以去加载别的类。

这也是我们在测试时为什么发现System.class.getClassLoader()结果为null的原因,这并不表示System这个类没有类加载器,而是它的加载器比较特殊,是BootstrapClassLoader,由于它不是Java类,因此获得它的引用肯定返回null。

  1. 委托机制具体含义
    当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
  • 首先当前线程的类加载器去加载线程中的第一个类(假设为类A)。
    注:当前线程的类加载器可以通过Thread类的getContextClassLoader()获得,也可以通过setContextClassLoader()自己设置类加载器。
  • 如果类A中引用了类B,Java虚拟机将使用加载类A的类加载器去加载类B。
  • 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
  1. 委托机制的意义 — 防止内存中出现多份同样的字节码
    比如两个类A和类B都要加载System类:
  • 如果不用委托而是自己加载自己的,那么类A就会加载一份System字节码,然后类B又会加载一份System字节码,这样内存中就出现了两份System字节码。
  • 如果使用委托机制,会递归的向父类查找,也就是首选用Bootstrap尝试加载,如果找不到再向下。这里的System就能在Bootstrap中找到然后加载,如果此时类B也要加载System,也从Bootstrap开始,此时Bootstrap发现已经加载过了System那么直接返回内存中的System即可而不需要重新加载,这样内存中就只有一份System的字节码了。

一道面试题

  • 能不能自己写个类叫java.lang.System

答案:通常不可以,但可以采取另类方法达到这个需求。
解释:为了不让我们写System类,类加载采用委托机制,这样可以保证爸爸们优先,爸爸们能找到的类,儿子就没有机会加载。而System类是Bootstrap加载器加载的,就算自己重写,也总是使用Java系统提供的System,自己写的System类根本没有机会得到加载。

但是,我们可以自己定义一个类加载器来达到这个目的,为了避免双亲委托机制,这个类加载器也必须是特殊的。由于系统自带的三个类加载器都加载特定目录下的类,如果我们自己的类放在一个特殊的目录,那么系统的加载器就无法加载,也就是最终还是由我们自己的加载器加载。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327015.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性结构VS非线性结构

线性结构 线性结构作为最常用的数据结构&#xff0c;其特点是数据元素之间存在一对一的线性关系 线性结构有两种不同的存储结构&#xff0c;即顺序存储结构和链式存储结构。顺序存储的线性表称为顺序表&#xff0c;顺序表中的存储元素是连续的 链式存储的线性表称为链表&#…

ES报错:Connection reset by peer 解决经历

http://nicethemes.cn/news/txtlist_i28391v.html 这次来分享一下ES报错&#xff1a;java.io.IOException: Connection reset by peer 的解决经历 问题描述 本人最近负责了定时获取Prometheus Metrics并发送到ES做持久化存储的任务。然而在Metrics采集粒度从3分钟变为1小时后…

云计算设计模式(一)缓存预留模式

云带来的改变是显而易见的&#xff0c;云计算是一种按使用量付费的模式&#xff0c;这种模式提供可用的、便捷的、按需的网络访问&#xff0c; 进入可配置的计算资源共享池&#xff08;资源包括网络&#xff0c;服务器&#xff0c;存储&#xff0c;应用软件&#xff0c;服务&am…

Thread.currentThread().getContextClassLoader() 和 Class.getClassLoader()区别

转载自 Thread.currentThread().getContextClassLoader() 和 Class.getClassLoader()区别 查了一些资料也不是太明白两个的区别&#xff0c;但是前者是最安全的用法 打个简单的比方&#xff0c;你一个WEB程序&#xff0c;发布到Tomcat里面运行。 首先是执行Tomcat org.apache.c…

批量删除文件

git bash 运行 rm -rf *.class 删除当前文件夹下所有的.class文件

稀疏数组与二维数组相互转化

图示 二维数组转稀疏数组的思路 遍历 原始的二维数组&#xff0c;得到有效数据的个数 sum根据sum 就可以创建 稀疏数组 sparseArr int[sum 1] [3]将二维数组的有效数据数据存入到 稀疏数组 稀疏数组转原始的二维数组的思路 先读取稀疏数组的第一行&#xff0c;根据第一行的…

云计算设计模式(二)——断路器模式

云带来的改变是显而易见的&#xff0c;云计算是一种按使用量付费的模式&#xff0c;这种模式提供可用的、便捷的、按需的网络访问&#xff0c; 进入可配置的计算资源共享池&#xff08;资源包括网络&#xff0c;服务器&#xff0c;存储&#xff0c;应用软件&#xff0c;服务&am…

Class.forName()和ClassLoader.getSystemClassLoader().loadClass()区别

转载自 Class.forName&#xff08;&#xff09;和ClassLoader.getSystemClassLoader().loadClass&#xff08;&#xff09;区别 class A {static {System.out.println("Class A is Loading now");}public A(){System.out.println("A new Class A instance is cr…

excel打开csv 出现乱码怎么解决 逗号分隔

excel打开csv 出现乱码怎么解决 https://jingyan.baidu.com/article/ac6a9a5e4c681b2b653eacf1.html CSV是逗号分隔值的英文缩写&#xff0c;通常都是纯文本文件。CSV格式是分隔的数据格式&#xff0c;有字段/列分隔的逗号字符和记录/行分隔换行符。通常CSV文件可以用EXCEL正常…

mybatis报错:java.lang.IllegalArgumentException: Mapped Statements collection does not contain

在做mybatis案例的时候发现了一个问题&#xff0c;报错如下&#xff1a; org.apache.ibatis.exceptions.PersistenceException:### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for org.dao.…

在ASP.NET Core下使用SignalR技术

一、前言 上次我们讲到过如何在ASP.NET Core中使用WebSocket,没有阅读过的朋友请参考 WebSocket in ASP.NET Core 文章 。这次的主角是SignalR它为我们提供了简化操作WebSocket的框架。 ASP .NET SignalR 是一个ASP.NET 下的类库&#xff0c;可以在ASP.NET 的Web项目中实现实时…

ClassLoader 详解及用途

转载自 ClassLoader 详解及用途 ClassLoader主要对类的请求提供服务&#xff0c;当JVM需要某类时&#xff0c;它根据名称向ClassLoader要求这个类&#xff0c;然后由ClassLoader返回这个类的class对象。 1.1 几个相关概念ClassLoader负责载入系统的所有Resources&#xff08;…

mybatis简单案例源码详细【注释全面】——前期准备

mybatis 是个什么东西&#xff0c;这里就不必说了&#xff0c;大家去网上搜搜看就行了&#xff0c;在这里我主要是分享一下最基本的增删改查案例以及配置信息&#xff0c;测试信息。 首先我们创建个数据库&#xff1a; /* SQLyog 企业版 - MySQL GUI v8.14 MySQL - 5.5.40 : …

用数组模拟队列的实现

package com.atguigu.queue;import jdk.nashorn.internal.ir.ReturnNode;import java.util.Scanner;/*** 创建人 wdl* 创建时间 2021/3/17* 描述*/ public class ArrayQueueDemo {public static void main(String[] args) {//测试一把//创建一个队列ArrayQueue queue new Arra…

时间格式转换2020-04-09T23:00:00.000+08:00

时间格式转换2020-04-09T23:00:00.00008:00 /*** 日期格式转换yyyy-MM-ddTHH:mm:ss.SSSXXX (yyyy-MM-ddTHH:mm:ss.SSSZ) TO yyyy-MM-dd HH:mm:ss* 2020-04-09T23:00:00.00008:00 TO 2020-04-09 23:00:00* throws ParseException*/public static String dealDateFormat(String…

云计算设计模式(三)——补偿交易模式

撤消由一系列步骤&#xff0c;它们共同限定了最终一致性操作中&#xff0c;如果一个或多个步骤失败执行的工作。按照最终一致性模型&#xff0c;业务实现复杂的业务流程和工作流的云托管的应用程序中很常见。 背景和问题 在云中运行的应用程序频繁修改数据。此数据可跨在各种地…

java反射 修改静态方法的值 setAccessible

转载自 java反射 修改静态方法的值 setAccessible 这几天闲来无事。在网上看了一个题目&#xff0c;相信大家都知道这个题目 static void change(String str){str"welcome";}public static void main(String[] args) {String str "123";change(str);Syste…

mybatis简单案例源码详细【注释全面】——实体层(User.java)

/** * Title: Users.java * Package org.entity * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-10-5 下午6:53:06 * version V1.0 */ package org.entity;import java.util.Date;/** * * 项目名称&#xff1a;s…

API网关Ocelot 使用Polly 处理部分失败问题

在实现API Gateway过程中&#xff0c;另外一个需要考虑的问题就是部分失败。这个问题发生在分布式系统中当一个服务调用另外一个服务超时或者不可用的情况。API Gateway不应该被阻断并处于无限期等待下游服务的状态。但是&#xff0c;如何处理这种失败依赖于特定的场景和具体服…