一、什么是类的加载:

如上图,java文件通过编译器变成了.class文件,接下来类加载器又将这些.class文件加载到JVM中。其中类装载器的作用其实就是类的加载。

二.原理 (类的加载过程及其最终产品):

JVM将class文件字节码文件加载到内存中, 并将这些静态数据转换成方法区中的运行时数据结构,在堆(并不一定在堆中,HotSpot在方法区中)中生成一个代表这个类的java.lang.Class 对象,作为方法区类数据的访问入口。

三.过程(类的生命周期):

类加载机制分为五个部分:加载,验证,准备,解析,初始化
其中加载、检验、准备、初始化和卸载这个五个阶段的顺序是固定的,而解析则未必。为了支持动态绑定,解析这个过程可以发生在初始化阶段之后。

加载:

加载过程主要完成三件事情:

  1. 通过类的全限定名来获取定义此类的二进制字节流
  2. 将这个类字节流代表的静态存储结构转为方法区的运行时数据结构
  3. 在堆中生成一个代表此类的java.lang.Class对象,作为访问方法区这些数据结构的入口。

这个过程主要就是类加载器完成。

校验:

此阶段主要确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机的自身安全。

  1. 文件格式验证:基于字节流验证。
  2. 元数据验证:基于方法区的存储结构验证。
  3. 字节码验证:基于方法区的存储结构验证。
  4. 符号引用验证:基于方法区的存储结构验证。

准备:

为类变量分配内存,并将其初始化为默认值。(此时为默认值,在初始化的时候才会给变量赋值)即在方法区中分配这些变量所使用的内存空间。

例如: public static int value = 123;

此时在准备阶段过后的初始值为0而不是123;将value赋值为123的putstatic指令是程序被编译后,存放于类构造器<client>方法之中。

解析:

把类型中的符号引用转换为直接引用。

  • 符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。
  • 直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在

主要有以下四种:

  1. 类或接口的解析
  2. 字段解析
  3. 类方法解析
  4. 接口方法解析

初始化:

初始化阶段是执行类构造器<client>方法的过程。<client>方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证<client>方法执行之前,父类的<client>方法已经执行完毕。如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成<client>()方法。

java中,对于初始化阶段,有且只有以下五种情况才会对要求类立刻“初始化”(加载,验证,准备,自然需要在此之前开始):

  1. 使用new关键字实例化对象、访问或者设置一个类的静态字段(被final修饰、编译器优化时已经放入常量池的例外)、调用类方法,都会初始化该静态字段或者静态方法所在的类。
  2. 初始化类的时候,如果其父类没有被初始化过,则要先触发其父类初始化。
  3. 使用java.lang.reflect包的方法进行反射调用的时候,如果类没有被初始化,则要先初始化。
  4. 虚拟机启动时,用户会先初始化要执行的主类(含有main)
  5. jdk 1.7后,如果java.lang.invoke.MethodHandle的实例最后对应的解析结果是 REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄,并且这个方法所在类没有初始化,则先初始化。

四.类加载器:

把类加载阶段的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作交给虚拟机之外的类加载器来完成。这样的好处在于,我们可以自行实现类加载器来加载其他格式的类,只要是二进制字节流就行,这就大大增强了加载器灵活性。系统自带的类加载器分为三种:

  1. 启动类加载器。
  2. 扩展类加载器。
  3. 应用程序类加载器。

双亲委派机制工作过程:

如果一个类加载器收到了类加载器的请求.它首先不会自己去尝试加载这个类.而是把这个请求委派给父加载器去完成.每个层次的类加载器都是如此.因此所有的加载请求最终都会传送到Bootstrap类加载器(启动类加载器)中.只有父类加载反馈自己无法加载这个请求(它的搜索范围中没有找到所需的类)时.子加载器才会尝试自己去加载。

双亲委派模型的优点:java类随着它的加载器一起具备了一种带有优先级的层次关系,不会导致各种自定义加载器家在核心api,统一规范。

例如类java.lang.Object,它存放在rt.jart之中.无论哪一个类加载器都要加载这个类.最终都是双亲委派模型最顶端的Bootstrap类加载器去加载.因此Object类在程序的各种类加载器环境中都是同一个类.相反.如果没有使用双亲委派模型.由各个类加载器自行去加载的话.如果用户编写了一个称为“java.lang.Object”的类.并存放在程序的ClassPath中.那系统中将会出现多个不同的Object类.java类型体系中最基础的行为也就无法保证.应用程序也将会一片混乱.

4、自定义类加载器:

在这一部分第一小节中,我们提到了java系统为我们提供的三种类加载器,还给出了他们的层次关系图,最下面就是自定义类加载器,那么我们如何自己定义类加载器呢?这主要有两种方式

(1)遵守双亲委派模型:继承ClassLoader,重写findClass()方法。

(2)破坏双亲委派模型:继承ClassLoader,重写loadClass()方法。 通常我们推荐采用第一种方法自定义类加载器,最大程度上的遵守双亲委派模型。

我们看一下实现步骤

(1)创建一个类继承ClassLoader抽象类

(2)重写findClass()方法

(3)在findClass()方法中调用defineClass()。

类加载机制-深入理解jvm的更多相关文章

  1. Java类加载机制的理解

    算上大学,尽管接触Java已经有4年时间并对基本的API算得上熟练应用,但是依旧觉得自己对于Java的特性依然是一知半解.要成为优秀的Java开发人员,需要深入了解Java平台的工作方式,其中类加载机 ...

  2. 类加载机制(深入理解JAVA虚拟机学习笔记)

    1.类加载机制的定义 将class文件加载到内存,然后对class文件中的数据进行校验.解析和初始化,转换成可以被虚拟机直接使用的JAVA类型,这就是虚拟机的类加载机制.(在JAVA中,类的加载.连接 ...

  3. JVM,Tomcat与OSGi类加载机制比较

    首先一个思维导图来看下Tomcat的类加载机制和JVM类加载机制的过程 类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加载. 比如JVM启动时,会通过不同的类加载器加载 ...

  4. JVM基础系列第7讲:JVM 类加载机制

    当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...

  5. 图解JVM和Tomcat类加载机制

    说到本篇的tomcat类加载机制,不得不说翻译学习tomcat的初衷. 之前实习的时候学习javaMelody的源码,但是它是一个Maven的项目,与我们自己的web项目整合后无法直接断点调试.后来同 ...

  6. 一夜搞懂 | JVM 类加载机制

    前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 学习导图 一.为什么要学习类加载机制? 今天想跟大家唠嗑唠嗑Java的类加载机制,这是Java的一个很重要的创 ...

  7. JVM初探(三):类加载机制

    一.概述 我们知道java代码会被编译为.class文件,这里class文件中的类信息最终还是需要jvm加载以后才能使用. 事实上,虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转 ...

  8. Java JVM类加载机制

    虚拟机的类加载机制是:JVM把描述类的数据从.class文件加载到内存,并对数据进行校验.解析.初始化,最终形成可以被JVM直接使用的Java类型. 加载.连接(验证.准备.解析).初始化.使用.卸载 ...

  9. jvm虚拟机笔记<三> 类文件结构与类加载机制

    java虚拟机具有语言无关系,它只和“class文件“这种特定的二进制文件格式绑定. 不同语言的编译器将对应的程序编译成字节码文件(*.class),送给jvm执行. class文件本质上就是一张表, ...

  10. Java面试题:JVM中的类加载机制

    JVM 的类加载机制是指 JVM 把描述类的数据从 .class 文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是 JVM 的类加载机制. 类 ...

随机推荐

  1. Mysql数据库插入数据时出现Unknown column ‘admin‘ in ‘field list‘错误

    报错内容 报错原因 字段和插入的值所用的引号不对 解决方案 insert into t_user(`username`,`password`,`email`) VALUES(`admin`,`admi ...

  2. 可视化学习:WebGL的基础使用

    引言 继续复习可视化的学习.WebGL和其他Web端的图形系统存在很大的不同,是OpenGL ES规范在浏览器的实现,它最大的不同就在于它更接近底层,可以由开发者直接操作GPU来实现绘图,性能很好,可 ...

  3. [ABC246F] typewriter

    Problem Statement We have a typewriter with $N$ rows. The keys in the $i$-th row from the top can ty ...

  4. 内核模块(.ko) 开发入门

    内核模块时指的是在操作系统内核中动态加载的一段代码,它可以扩展和增强操作系统的功能.内核模块通常用于为操作系统添加新的设备驱动程序.文件系统.网络协议栈等功能. 内核模块是以二进制形式存在的(*.ko ...

  5. 简单几行实现sliver上线提醒

    准备魔改sliver去掉一些特征什么的,这里记录一下最简单实现上线消息通过企业微信机器人提醒的方式,这很简单也有很多不足还需要接着改的 protobuf中对消息Beacon和Session的定义如下, ...

  6. ESP32 IDF iic通信( 已验证) C语言

    关于iic原理建议B站自己看视频去, 然后本文主要实现了esp32的初始化, 写地址, 写数据, 读数据的功能, 从机的代码因为展示不需要,没写. 园子里面有个兄弟写了iic的代码.但是里面有点毒,多 ...

  7. 良心国产工具,比Xshell好用还免费!

    使用或维护Linux系统的都知道,我们日常对服务器的操作,一般都会借助SSH工具远程登录到服务器之后进行操作.常用的SSH工具有不少,比如:Xshell.Putty.SSH Secure Shell ...

  8. GeoServer发布地图服务(WMS、WFS)

    目录 1. 概述 2. 矢量数据源 3. 栅格数据源 1. 概述 我们知道将GIS数据大致分成矢量数据和栅格数据(地形和三维模型都是兼具矢量和栅格数据的特性).但是如果用来Web环境中,那么使用图片这 ...

  9. ifconfig详解

    linux下ifconfig命令详解 ifconfig 是一个用来查看.配置.启用或禁用网络接口的工具,这个工具极为常用的.可以用这个工具来临时性的配置网卡的IP地址.掩码.广播地址.网关等.也可以把 ...

  10. Spring Boot与Shiro和Mybatis整合

    1:shiro是什么? Apache Shiro 是ASF旗下的一款开源软件 shrio是一款强大而灵活的安全框架 可为任何应用提供安全保障- 从命令行应用.移动应用到大型网络及企业应用 2:shir ...