【小家Java】从原理层面理解Java中的类加载器:ClassLoader、双亲委派模型、线程上下文类加载器(上)

简介: 【小家Java】从原理层面理解Java中的类加载器:ClassLoader、双亲委派模型、线程上下文类加载器(上)

前言


java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java 类,即 java.lang.Class类的一个实例。


类加载器是平时开发中基本不会接触的问题,但是在高阶应用中必须要深入其原理才能予以自用。比如tomcat加载web-jar就是通过自己的ClassLoader去加载进来的。同时这个也是高级技术常常会问到的一个专题,因此本文针对于此做一些叙述,希望对大家能够有所帮助


普通的java开发者其实用到的不多,但对于某些框架开发者来说却非常常见。理解ClassLoader的加载机制,也有利于我们编写出更高效的代码。ClassLoader的具体作用就是将class文件加载到jvm虚拟机中去,程序就可以正确运行了。


Java程序启动时,并不是一次把所有的类全部加载后再运行,它总是先把保证程序运行的基础类一次性加载到jvm中,其它类等到jvm用到的时候再加载,这样的好处是节省了内存的开销,因为java最早就是为嵌入式系统而设计的,内存宝贵,这是一种可以理解的机制,而用到时再加载这也是java动态性的一种体现

类加载器的三个机制(约束)


委托


委托机制是指将加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或者加载这个类,那么再加载它。(双亲委派模型)


image.png


可见性


可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类


单一性


单一性原理是指仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类


类加载器的种类


image.png


JAVA类装载方式,有两种:


   1.隐式装载, 程序在运行过程中当碰到通过 new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中。


    2.显式装载, 通过class.forname()等方法,显式加载需要的类


有三种默认使用的类加载器:Bootstrap类加载器、Extension类加载器和System类加载器(或者叫作Application类加载器)。每种类加载器都有设定好从哪里加载类。


  • Bootstrp加载器:是用C++语言写的(其余均为Java写的),它是在Java虚拟机启动后初始化的,它主要负责加载rt.jar中的类。(JDK的核心类,如String、Integer等等类) 它对rt.jar的加载全盘负责


  • ExtClassLoader:Bootstrp loader加载ExtClassLoader,并且将ExtClassLoader的父加载器设置为Bootstrp loader.ExtClassLoader。是用Java写的,具体来说就是 sun.misc.Launcher$ExtClassLoader。xtClassLoader主要加载%JAVA_HOME%/jre/lib/ext,此路径下的所有classes目录以及java.ext.dirs系统变量指定的路径中类库。
  •  AppClassLoader:Bootstrp loader加载完ExtClassLoader后,就会加载AppClassLoader,并且将AppClassLoader的父加载器指定为 ExtClassLoader。AppClassLoader也是用Java写成的,它的实现类是 sun.misc.Launcher$AppClassLoader。 另外我们知道ClassLoader中有个getSystemClassLoader方法,此方法返回的正是AppclassLoader。


System.out.println(System.getProperty(“java.class.path”));可以获得classpath的配置,也就是system classloader 加载的类

image.png


  • AppClassLoader主要负责加载classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器

image.png


需要注意的是,如下例子:


    public static void main(String[] args) {
        System.out.println(String.class.getClassLoader()); //null
        System.out.println(Main.class.getClassLoader().getParent()); //sun.misc.Launcher$ExtClassLoader@23fc625e
    }


我们发现String类的类加载器为null,肿么回事呢?


其实前面有提到Bootstrap Loader是用C++语言写的,依java的观点来看,逻辑上并不存在Bootstrap Loader的类实体,所以在java程序代码里试图打印出其内容时,我们就会看到输出为null。


Class类没有public的构造方法,Class对象是在装载类时由JVM通过调用类装载器中的defineClass()方法自动构造的。

相关文章
|
22天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
61 0
|
1月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
98 16
|
2月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
2月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
3月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
310 83
|
3月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
145 0
|
3月前
|
存储 Java 调度
Java虚拟线程:轻量级并发的革命性突破
Java虚拟线程:轻量级并发的革命性突破
267 83
|
4月前
|
移动开发 Java
说一说 Java 是如何实现线程间通信
我是小假 期待与你的下一次相遇 ~

热门文章

最新文章