类加载器

  • 类加载器
    • 类加载器的分类
    • 启动类加载器(引导类加载器,Bootstra ClassLoader)
    • 扩展类加载器(Extension ClassLoader)
    • 用户自定义类加载器

类加载器

类加载器的分类
  • JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Definded ClassLoader)
  • 从概念上来讲,自定义类加载器是程序中由开发人员定义的一类类加载器,但是Java虚拟机规范当中却没这么定义,而是把所有的派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。
  • 无论类加载器的类型如何划分,在程序当中最常见的类加载器始终只有3个,**引导类加载器、扩展类加载器、系统类加载器。**其中除了引导类加载器,剩下的都是派生于ClassLoader的类,也就是自定义类加载器。

类加载器的获取代码演示

public class ThreadTest {public static void main(String[] args) {//获取系统类加载器  sun.misc.Launcher$AppClassLoader@18b4aac2ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();System.out.println(systemClassLoader);//获取上层的扩展类加载器  sun.misc.Launcher$ExtClassLoader@1540e19dClassLoader extClassLoader = systemClassLoader.getParent();System.out.println(extClassLoader);//获取上层的引导类加载器  nullClassLoader bootstrapClassLoader = extClassLoader.getParent();System.out.println(bootstrapClassLoader);//对于用户自定义类来说  sun.misc.Launcher$AppClassLoader@18b4aac2ClassLoader classLoader = ThreadTest.class.getClassLoader();System.out.println(classLoader);}
}
启动类加载器(引导类加载器,Bootstra ClassLoader)
  • 这个类加载使用C/C++语言实现的,嵌套在JVM内部
  • 这个加载器用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar、resources.jar 或者是 sun.boot.class.path路径下的内容),用于提供JVM的自身需要的类
  • 并不继承自java.lang.ClassLoader,没有父类加载器。
  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器
  • 出于安全考虑,BootStrap启动类加载器自家在包名为java、javax、sun等开头的类
扩展类加载器(Extension ClassLoader)
  • Java语言编写,由sun.misc.Launcher$ExtClassLoader实现
  • 派生于ClassLoader类
  • 父类加载器为启动类加载器
  • 从java.ext.dirs系统属性所指定的目录中加载类库,或者从JDK的按抓个目录的jre/lib/ext 子目录(扩展目录)下加载类库。如果用户创建的JAR放在次目录下,也会自动由扩展类加载器加载。

下面对类的加载器进行测试:

package com.classload.chapter01;import sun.misc.Launcher;
import sun.security.ec.CurveDB;import java.net.URL;public class ThreadTest {public static void main(String[] args) {System.out.println("=====启动类加载器=====");URL[] urLs = Launcher.getBootstrapClassPath().getURLs();for (URL url : urLs) {System.out.println(url);}System.out.println("=====扩展类加载器=====");String property = System.getProperty("java.ext.dirs");for (String path : property.split(";")) {System.out.println(path);}System.out.println("=====类加载器测试=====");System.out.println("测试的类: CurvDB");ClassLoader classLoader = CurveDB.class.getClassLoader();System.out.println(classLoader);}
}
# 测试结果
=====启动类加载器=====
file:/D:/JDK/jdk1.8.0_131/jre/lib/resources.jar
file:/D:/JDK/jdk1.8.0_131/jre/lib/rt.jar
file:/D:/JDK/jdk1.8.0_131/jre/lib/sunrsasign.jar
file:/D:/JDK/jdk1.8.0_131/jre/lib/jsse.jar
file:/D:/JDK/jdk1.8.0_131/jre/lib/jce.jar
file:/D:/JDK/jdk1.8.0_131/jre/lib/charsets.jar
file:/D:/JDK/jdk1.8.0_131/jre/lib/jfr.jar
file:/D:/JDK/jdk1.8.0_131/jre/classes
=====扩展类加载器=====
D:\JDK\jdk1.8.0_131\jre\lib\ext
C:\Windows\Sun\Java\lib\ext
=====类加载器测试=====
测试的类: CurvDB
sun.misc.Launcher$ExtClassLoader@29453f44

上述代码的解释:
1、获取引导类加载器的扫描目录的时候,使用sun.misc.Launcher.getBootstrapClassPath().getURLs();方法获取扫描的所有jar包的目录
2、获取扩展类加载器的扫描路径的时候使用的是System.getProperty("java.ext.dirs");方法因为系统属性的java.ext.dirs当中加载类库
3、使用一个类去测试他的类加载器使用class的getClassLoader方法,因为CurvDB是D:\JDK\jdk1.8.0_131\jre\lib\ext目录下的sunec包下的一个类,所以使用的类加载器是扩展类加载器。

但是假如说找String这个核心包下的类呢?来试一试

public static void main(String[] args) {ClassLoader classLoader1 = String.class.getClassLoader();System.out.println(classLoader1);
}测试结果:null

因为核心包走的都是引导类加载器,而且引导类加载器都是C和C++写的,所以说获取不到。

用户自定义类加载器

用户自定义类加载器的实现步骤:
1、开发者会根据抽象类java.lang.ClassLoader类的方式,实现自己的类加载器,来满足一些需求。
2、在JDK1.2之前,在自定义类加载器时,总会去继承ClassLoader类并重写loadClass() 方法,从而实现自定义的类加载器,但是在JDK1.2之后已经不再建议用户去覆盖loadCass() 方法,而是建议把自定义的类加载逻辑写到findClass() 方法当中。
3、在编写自定义类加载器的时候,如果没有太过于复杂的需求,可以直接继承URLClassLoader类,这样就可以避免自己去编写findClass() 方法机器获取字节码流的方式,是自定义类加载器编写更加的简洁。

下面写一段代码来理解一下:

//CustomClassLoader.java类
public class CustomClassLoader extends ClassLoader {private String path;/*** @param path 需要加载的class文件的路径*/public CustomClassLoader(String path) {this.path = path;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {byte[] result = getClassData();if(result == null) {throw new FileNotFoundException();} else {return defineClass(name, result, 0, result.length);}} catch (FileNotFoundException e) {e.printStackTrace();}return super.findClass(name);}/*** @return  返回class文件的二进制流** 把文件读出的数据放到内存的二进制输出流* 把二进制输出流返回成byte数组** 这里使用构造函数的path来加载.class文件*/private byte [] getClassData() {File file = new File(path);if(file.exists()) {InputStream in = null;ByteArrayOutputStream out = null;try {in = new FileInputStream(file);out = new ByteArrayOutputStream();int length = 0;byte [] bytes = new byte[1024];while ((length = in.read(bytes)) != -1) {out.write(bytes, 0, length);}} catch (IOException e) {e.printStackTrace();} finally {if(in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}}return out.toByteArray();} else {return null;}}
}

测试代码:

public class ThreadTest {public static void main(String[] args) throws ClassNotFoundException {CustomClassLoader loader = new CustomClassLoader("E:\\IDEA\\JavaBase\\ClassLoad\\target\\classes\\com\\classload\\chapter01\\HelloLoader.class");Class<?> aClass = loader.loadClass("com.classload.chapter01.HelloLoader");System.out.println("类加载器是:" + aClass.getClassLoader());Object object = aClass.newInstance();System.out.println(object);}
}# 输出样例:
类加载器是:sun.misc.Launcher$AppClassLoader@18b4aac2
execute
com.classload.chapter01.HelloLoader@677327b6

1、首先需要使用类的路径加载.class 文件,把class文件转换为二进制数组
2、根据二进制数组和文件的包名+文件名,调用ClassLoader类的defineClass方法,完成类的加载过程

在类加载完成之后,可以调用newInstance() 方法来获取类的实例,使用getClassLoader()方法可以获取类的加载器

好了,类的三种加载器就写到这里,感谢你能看到最后,谢谢支持。
对了,如果哪里写的不对,在下面的评论区跟我说一下哈。886

JVM类加载器分类和解析相关推荐

  1. Java高并发编程详解系列-JVM类加载器

    之前的博客中提到了类加载的过程,提到了双亲委托机制,提到了关于类加载器的概念,这篇博客就来给大家分享一下什么是JVM的类加载器.通过实战的方式来了解一下类加载器器到底是什么. JVM类加载器分类    ...

  2. jvm:类加载器与双亲委派模型

    两个类相等需要类本身相等,并且使用同一个类加载器进行加载.这是因为每一个类加载器都拥有一个独立的类名称空间. 这里的相等,包括类的 Class 对象的 equals() 方法.isAssignable ...

  3. JVM—类加载器和双亲委派模型

    关注微信公众号:CodingTechWork,一起工作学习总结. 文章目录 引言 类加载器 类与类加载器关系 类加载器分类 启动类加载器 扩展类加载器 应用程序类加载器 双亲委派模型 介绍 工作流程 ...

  4. jvm类加载器以及双亲委派

    首先来了解几个概念: 类加载: 概念:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验--转换解析--初始化,最终形成能被java虚拟机直接使用的java类型,就是jvm的类加载机制. ...

  5. JVM 类加载器详解

    类加载器作用: 类加载器子系统作用: 1. 类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识. 2. ClassLoader只负责class文件的加载 ...

  6. 《Java虚拟机原理图解》5. JVM类加载器机制与类加载过程

    参考网址:http://blog.csdn.net/luanlouis/article/details/50529868 0.前言 读完本文,你将了解到: 一.为什么说Jabalpur语言是跨平台的 ...

  7. 彻底搞懂JVM类加载器:基本概念

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 阿杜的世界 来源 | javaadu 在Java面试中,在考察完项目经验.基础技术 ...

  8. java类加载器分类_Java 类加载器的种类

    1.定义: 寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件. 2.种类: BootstrapClassLoader:用C++编写的,装载jre中的核心类库: ExtClassLoader ...

  9. 22-09-02 西安 JVM 类加载器、栈、堆体系、堆参数调优、GC垃圾判定、垃圾回收算法、对象的finalize机制

    这篇文章不少地方都截图了宋红康老师的课件,实在他jvm这块讲的真好.连接地址如下: 尚硅谷宋红康JVM全套教程(详解java虚拟机)_哔哩哔哩_bilibili JVM入门 1.JVM结构图 JVM是 ...

最新文章

  1. 从理论到实践,Top选手带你进入数据竞赛的大门
  2. 1-6 数据查询(下)——复杂查询
  3. 一个模型处理多个任务
  4. UltraTextEditor
  5. 【转】三分钟了解Fiori背后的设计理念
  6. 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005...
  7. python制作一个计时器_如何在python中创建一个反应计时器作为GUI?
  8. 基于 Gitlab 交付 Go 程序的 Docker 镜像
  9. 看过来,说的就是你!
  10. git学习笔记-(10-分支例子)
  11. html转换成avi,HTML_视频转换大师WinMPG Video Convert 6.63,支持格式丰富,可快速完成AVI(RM - phpStudy...
  12. 软件需求工程 高校教学平台 项目总体计划
  13. ubuntu安装阿里源
  14. java 热度算法_Raddit算法Java实现
  15. 2020ICPC·小米 网络选拔赛第一场(Matrix Subtraction (二维差分))
  16. arm模拟器手机版_ARM模拟器——SkyEye的使用
  17. 边云协同的优点_关于边缘计算和边云协同,看这一篇就够了
  18. NIST《零信任安全架构标准》简单解读
  19. 起名算法 php,取名测试打分
  20. 用Python做个小网站(MVC架构)

热门文章

  1. 2021-03-09CSS学习第一天
  2. 美丽说、蘑菇街这类网站
  3. Liunx文件操作命令(touch、cat、vim、more、less、cp、mv、rm、head、tail、file、find)
  4. 下列计算机应用中属于计算机辅助教学的事,2017年计算机基础考试题库完整版「附答案解析」...
  5. 如何让代码看起来有万佛朝宗的气势
  6. stackEdit的使用
  7. 基于位置的服务(简介)
  8. 物联网卡是可以拨打电话的智能卡吗
  9. 小程序前端页面访问数据出现undefined
  10. Play with mini2440 ARM Board ( by quqi99)