JVM类的加载和类的加载器

一.类的加载过程

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

1.加载

一般来说加载分为以下几步:

(1) 通过一个类的全限定名获取此类的二进制字节流

(2) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

(3) 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

加载.class文件的方式

  • 从本地系统中直接加载

  • 通过网络获取,典型场景: web Applet

  • 从zip压缩包中读取,成为口后jar、war格式的基础

  • 运行时计算生成,使用最多的是:动态代理技术由其他文件生成,典型场景: JSP应用

  • 从专有数据库中提取.class文件,比较少见

  • 从加密文件中获取,典型的防class文件被反编译的保护措施

2.链接

2.1验证(Verify)

  • 目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。
  • 主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证

2.2准备(Prepare)

  • 为类变量分配内存并且设置该类变量的默认初始值,即零值。

  • 这里不包含用final修饰的static,因为fina1在编译的时候就会分配了,准备阶段会显式初始化;

  • 这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中

2.3解折(Resolve)

  • 将常量池内的符号引用转换为直接引用的过程。

  • 解析操作往往会伴随着JVM在执行完初始化之后再执行。

  • 符号引用就是一组符号来描述所引用的目标。符号引用的字面量形式明确定义在《java虚拟机规范》的class文件格式中。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

  • 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。对应常量池中的CONSTANT class info、CONSTANT Fieldref info、CONSTANT Methodref info等

3.初始化

  • 初始化阶段就是执行类构造器方法clinit的过程。

  • 此方法不需定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。

  • 构造器方法中指令按语句在源文件中出现的顺序执行。

  • clinit()不同于类的构造器。(关联: 构造器是虚拟机视角下的clinit

  • 若该类具有父类,JM会保证子类的clinit() 执行前,父类的clinit(已经执行完毕。

  • 虚拟机必须保证一个类的clinit方法在多线程下被同步加锁

二.类的加载器

4.作用

  • 类加载器子系统负责从文件系统或者网络中加载class文件,class文件在文件开头有特定的文件标识。

  • classLoader只负责class文件的加载,至于它是否可以运行,则由ExecutionEngine决定。

  • 加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是class文件中常量池部分的内存映射)

5.分类

  • JVM支持两种类型的类加载器,分别为引导类加载器 (BootstrapclassLoader)和自定义类加载器[user-Defined ClassLoader)
  • 从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象classLoader的类加载器都划分为自定义类加载器。
  • 无论类加载器的类型如何划分,在程序中我们最常见的类加载器始终只有3个,如下所示:

这里的四者之间的关系是包含关系。不是上层下层,也不是子父类的继承关系。

5.1启动类加载器(引导类加载器,Bootstrap ClassLoader)

  • 这个类加载使用C/C++语言实现的,嵌套在JVM内部。

  • 它用来加载Java的核心库 (JAVA HOME/re/lib/rt.jar、resources.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类

  • 并不继承自java.lang.classLoader,没有父加载器

  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器

  • 出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类

5.2扩展类加载器(Extension ClassLoader)

  • Java语言编写,由sun.misc.LauncherSExtClassLoader实现
  • 派生于classLoader类
  • 父类加载器为启动类加载器
  • 从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的ire/lib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。

5.3应用程序类加载器(系统类加载,AppclassLoader)

  • java语言编写,由sun.misc.LauncherSAppClassLoader实现

  • 派生于classLoader类

  • 父类加载器为扩展类加载器

  • 它负责加载环境变量classpath或系统属性 java.class.path 指定路径下的类库

  • 该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载

  • 通过classLoader.getSystemClassLoader0)方法可以获取到该类加载器

5.4用户自定义类加载器

在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方

为什么要自定义类加载器?

  • 隔离加载类
  • 修改类加载的方式
  • 扩展加载源
  • 防止源码泄漏

用户自定义类加载器实现步骤:

1.开发人员可以通过继承抽象类java.lang.classLoader类的方式,实现自己的类加载器,以满足一些特殊的需求

2.在JDK1.2之前,在自定义类加载器时,总会去继承classLoader类并重写loadclass0)方法,从而实现自定义的类加载类,但是在JDK1.2之后已不再建议用户去覆盖loadclass()方法,而是建议把自定义的类加载逻辑写在findclass()方法中

3.在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URIClassLoader类,这样就可以避免自己去编写findclass()方法及其获取字节码流的方式,使自定义类加载器编写更加简洁。

classLoader类,它是一个抽象类,其后所有的类加载器都继承自classLoader (不包括启动类加载器)

获取ClassLoader的途径

JVM类的加载和加载器的更多相关文章

  1. 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别

    [源码下载] 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) ...

  2. Flutter 开发从 0 到 1(四)ListView 下拉加载和加载更多

    在<APP 开发从 0 到 1(三)布局与 ListView>我们完成了 ListView,这篇文章将做 ListView 下拉加载和加载更多. ListView 下拉加载 Flutter ...

  3. JVM——类的加载过程

    附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...

  4. java架构之路-(JVM优化与原理)JVM类的加载机制

    话不多说,先上图. ***.class文件执行大概就是这样来走的.我们都知道我们的java文件经过编译以后会生成对应的class文件.先经过类装载子系统,然后塞进运行时内存模型的元空间,开始执行方法, ...

  5. JVM 类的加载机制

    在对类的实例化之前.JVM 一般会先进行初始化 主要经过如下几个阶段: 1.加载                       类加载的第一阶段,类加载时机有两个: 1.预加载:当虚拟机启动时,会预加载 ...

  6. Jvm类的加载机制

    1.概述 虚拟机加载Class文件(二进制字节流)到内存,并对数据进行校验.转换解析和初始化,最终形成可被虚拟机直接使用的Java类型,这一系列过程就是类的加载机制. 2.类的加载时机 类从被虚拟机加 ...

  7. JVM类的加载顺序

    前阵子看到阿里巴巴的一提面试题是关于java类的加载顺序 package com.mikey.demo.Test; class FatherVariable{ static { System.out. ...

  8. JVM 类的生命周期、类加载器

    类的加载.连接与初始化                  • 1. 加载:查找并加载类的二进制数据         • 2. 连接             – 2.1 验证:确保被加载的类的正确性   ...

  9. Unity -- AssetBundle(本地资源加载和加载依赖关系)

    1.本地资源加载 1).建立Editor文件夹 2).建立StreamingAssets文件夹和其Windows的子文件夹 将下方第一个脚本放入Editor 里面 脚本一  资源打包AssetBund ...

  10. jvm(1)类的加载(三)(线程上下文加载器)

    简介: 类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的. Java Applet 需要从远程下载 Java 类文件到浏览器中并执行. 现在类加载器在 ...

随机推荐

  1. 申威CPU的简单知识梳理

    摘要 最近有客户要用申威服务器了 自己很早之前简单测试过相关的CPU的服务器 但是感觉很多东西都不是很系统. 今天简单收集一下资料 希望对以后的工作有所帮助 申威CPU的创始 申威是解放军总参谋部第五 ...

  2. Linux 清理 防火墙已有IP地址的方法

    最简单的处理 for i in `firewall-cmd --zone=trusted --list-sources` ;do firewall-cmd --zone=trusted --remov ...

  3. C# AsyncLocal 是如何实现 Thread 间传值

    一:背景 1. 讲故事 这个问题的由来是在.NET高级调试训练营第十期分享ThreadStatic底层玩法的时候,有朋友提出了AsyncLocal是如何实现的,虽然做了口头上的表述,但总还是会不具体, ...

  4. React类组件中事件绑定this指向的三种方式

    有状态组件和无状态组件 函数组件又叫做无状态组件,类组件又叫做有状态组件. 状态又叫做数据 函数组件没有自己的状态,只负责静态页面的展示. 我们可以理解为纯ui展示.() 类组件有自己的状态,扶着更新 ...

  5. vue2-vue3监听子组件的生命周期的两种方式

    1.生命周期 生命周期是指:vue实例从创建到销毁这一系列过程.vue官网生命周期如下图所示: vue的生命周期有多少个 beforeCreate, created, beforeMount, mou ...

  6. css hover频繁闪烁

    今天遇见一个问题. 在鼠标放上 图片上的时候. 删除图标一直不停的闪烁. 我当时觉得很奇怪,父子关系的结构 不应该闪烁呀. 看了下html和css,发现子元素(要hover)的元素是绝对定位了的 于是 ...

  7. 【小测试】golang中使用string()来转换[]byte数组产生了拷贝

    下方是benchmark的数据差异: import ( "reflect" "unsafe" ) // NoAllocString convert []byte ...

  8. 【JS 逆向百例】医保局 SM2+SM4 国产加密算法实战

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...

  9. NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践

    NLP文本匹配任务Text Matching [无监督训练]:SimCSE.ESimCSE.DiffCSE 项目实践 文本匹配多用于计算两个文本之间的相似度,该示例会基于 ESimCSE 实现一个无监 ...

  10. VUE3子表格嵌套分页查询互相干扰的问题解决

    VUE3在表格中嵌套子表格子表格的分页查询互相干扰的问题解决 简单嵌套 如果不需要做子表格的分页查询,那么可以直接在主表格中嵌套子表格,有两种方式:一种是主表格加载的同时加载子表格数据,另一种是点击展 ...