热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

加载器和双亲委派

2019独角兽企业重金招聘Python工程师标准一道面试题能不能自己写个类叫java.lang.System?答案:通常不可以,但可

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

一道面试题

 

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

 

答案:通常不可以,但可以采取另类方法达到这个需求。 

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

 

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

 

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

 

JVM预定义的三种类型类加载器:

 

启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将 /lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。

标准扩展&#xff08;Extension&#xff09;类加载器&#xff1a;是由 Sun 的 ExtClassLoader&#xff08;sun.misc.Launcher$ExtClassLoader&#xff09;实现的。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。

系统&#xff08;System&#xff09;类加载器&#xff1a;是由 Sun 的 AppClassLoader&#xff08;sun.misc.Launcher$AppClassLoader&#xff09;实现的。它负责将系统类路径&#xff08;CLASSPATH&#xff09;中指定的类库加载到内存中。开发者可以直接使用系统类加载器。

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

 

双亲委派机制描述 

某个特定的类加载器在接到加载类的请求时&#xff0c;首先将加载任务委托给父类加载器&#xff0c;依次递归&#xff0c;如果父类加载器可以完成类加载任务&#xff0c;就成功返回&#xff1b;只有父类加载器无法完成此加载任务时&#xff0c;才自己去加载。

 

 

几点思考

 

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

 

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

 

委托机制具体含义 

当Java虚拟机要加载一个类时&#xff0c;到底派出哪个类加载器去加载呢&#xff1f;

 

首先当前线程的类加载器去加载线程中的第一个类&#xff08;假设为类A&#xff09;。 

注&#xff1a;当前线程的类加载器可以通过Thread类的getContextClassLoader()获得&#xff0c;也可以通过setContextClassLoader()自己设置类加载器。

如果类A中引用了类B&#xff0c;Java虚拟机将使用加载类A的类加载器去加载类B。

还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。

委托机制的意义 — 防止内存中出现多份同样的字节码 

比如两个类A和类B都要加载System类&#xff1a;

 

如果不用委托而是自己加载自己的&#xff0c;那么类A就会加载一份System字节码&#xff0c;然后类B又会加载一份System字节码&#xff0c;这样内存中就出现了两份System字节码。

如果使用委托机制&#xff0c;会递归的向父类查找&#xff0c;也就是首选用Bootstrap尝试加载&#xff0c;如果找不到再向下。这里的System就能在Bootstrap中找到然后加载&#xff0c;如果此时类B也要加载System&#xff0c;也从Bootstrap开始&#xff0c;此时Bootstrap发现已经加载过了System那么直接返回内存中的System即可而不需要重新加载&#xff0c;这样内存中就只有一份System的字节码了。

 


转载于:https://my.oschina.net/yan5845hao/blog/682293


推荐阅读
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • python模块之正则
    re模块可以读懂你写的正则表达式根据你写的表达式去执行任务用re去操作正则正则表达式使用一些规则来检测一些字符串是否符合个人要求,从一段字符串中找到符合要求的内容。在 ... [详细]
  • 处理POI导入Excel时遇到的数值单元格无法获取文本值问题
    在使用Apache POI库将数据从Excel导入到Java应用程序时,可能会遇到‘Cannot get a text value from a numeric cell’错误。本文将详细介绍该问题的原因及解决方案。 ... [详细]
  • C#实现文件的压缩与解压
    2019独角兽企业重金招聘Python工程师标准一、准备工作1、下载ICSharpCode.SharpZipLib.dll文件2、项目中引用这个dll二、文件压缩与解压共用类 ... [详细]
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • JVM钩子函数的应用场景详解
    本文详细介绍了JVM钩子函数的多种应用场景,包括正常关闭、异常关闭和强制关闭。通过具体示例和代码演示,帮助读者更好地理解和应用这一机制。适合对Java编程和JVM有一定基础的开发者阅读。 ... [详细]
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 我有一个从C项目编译的.o文件,该文件引用了名为init_static_pool ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • Eclipse中解决JDK源码断点调试失效的问题 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
  • C++ 开发实战:实用技巧与经验分享
    C++ 开发实战:实用技巧与经验分享 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
author-avatar
昆仑神奇_325
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有