类加载机制

把class文件加载到内存,并对数据进行校验,准备,解析,初始化,形成可以被虚拟机直接使用的字节码

类加载的时机(触发类的初始化)

  • 使用new关键字实例化对象
  • 读取一个类的静态代码块
  • 使用java.lang.reflect包的方式对类进行反射调用

类加载过程

整个生命周期包括:加载、校验、准备、解析、初始化、使用和卸载7个阶段。

  1. 加载:通过一个类的全限定名来获取定义此类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,在内存中生成一个代表这个类的Class对象,作为方法区这个类的各种数据的访问入口
  2. 校验:校验是连接阶段的第一步,这一阶段的目的是确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟自身的安全。
  3. 准备:准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法去中进行分配。这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。
  4. 解析:解析阶段是虚拟机将常量池内的符号(Class文件内的符号)引用替换为直接引用(指针)的过程。
  5. 初始化:初始化阶段是类加载过程的最后一步,开始执行类中定义的Java程序代码(字节码)。

加载

  • 通过全类名获取class文件的二进制字节流
  • 将字节流所代表的静态存储结构转换为方法区的运行时数据结构
  • 生成一个代表该类的class对象,作为方法区这些数据的访问入口

    根据字节码在java堆中生成一个代表这个类的java.lang.Class对象

校验

  • 验证Class文件中二进制字节流符合虚拟机的要求,不会涉及到虚拟机的安全
  • 文件格式验证
  • 元数据验证
  • 字节码验证

准备

  • 为类变量分配内存空间和设置初始值的阶段
  • 为新生对象分配内存

为新生对象分配内存

  • 如果Java堆内存是规整连续的,采用“指针碰撞”的分配方式
  • 如果不是连续规整的,采用“空闲列表”分配方式

内存是否规整取决于垃圾收集器是否带有压缩整理功能

这个初始值和初始化阶段的赋值不同,这里指的是变量的默认初始值,如果是final修饰的变量,就是赋予代码里制定的初始值

解析

虚拟机将符号引用替换为直接引用的过程

符号引用 :符号引用以一组符号来描述所引用的目标。符号引用可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,符号引用和虚拟机的布局无关。个人理解为:在编译的时候一个每个java类都会被编译成一个class文件,但在编译的时候虚拟机并不知道所引用类的地址,多以就用符号引用来代替,而在这个解析阶段就是为了把这个符号引用转化成为真正的地址的阶段。

直接引用 :直接引用和虚拟机的布局是相关的,不同的虚拟机对于相同的符号引用所翻译出来的直接引用一般是不同的。如果有了直接引用,那么直接引用的目标一定被加载到了内存中。

初始化

根据程序代码去初始化变量和其他资源,构造函数

类加载器

BootstrapLoader/负责加载系统类

注意一个很重要的问题,就是java在逻辑上并不存在BootstrapKloader的实体,因为它是c++编写的,所以打印其内容会是null

启动类加载器主要加载 jre/lib下的jar文件。

ExtClassLoader/负责加载扩展类//继承类和实现类

扩展类加载器主要加载 jre/lib/ext 下的jar文件。

AppClassLoader/负责加载应用类

应用程序类加载器主要加载 classpath 下的文件

Android类加载器

对于Android而言,最终的apk文件包含的是dex类型的文件,dex文件是将class文件重新打包,打包的规则又不是简单地压缩,而是完全对class文件内部的各种函数表,变量表进行优化,产生一个新的文件,即dex文件。因此加载这种特殊的Class文件就需要特殊的类加载器DexClassLoader。

双亲委派模型

当加载一个类时,会优先使用父类加载器加载,当父类加载器无法加载时才会使用子类加载器去加载。这么做的目的是为了避免类的重复加载

解释器

对字节码逐条解释执行,这种方式的执行速度相对会比较慢;重复执行需要重复解释

JIT(即时编译器)

在运行时,虚拟机将会把这些频繁调用的代码编译成与本地平台相关的机器码,并进行优化,可重复执行,缓存效率高

Class文件字节码结构

魔数—副版本号—主版本号—常量池计数器—常量池数据区—访问标志—类索引—父类索引—接口计数器—接口信息数据区—字段计数器—字段信息数据区—方法计数器—方法信息数据区—属性计数器—属性信息数据区

魔数:class文件的标志,确定这个文件是否为一个能被虚拟机接收的class文件

类B继承A,A、B两个类中都有静态变量、成员变量、静态代码块、构造方法执行顺序是什么?

1.父类【静态成员】和【静态代码块】,按在代码中出现的顺序依次执行。

2.子类【静态成员】和【静态代码块】,按在代码中出现的顺序依次执行。

3.父类的【普通成员变量被普通成员方法赋值】和【普通代码块】,按在代码中出现的顺序依次执行。

4.执行父类的构造方法。

5.子类的【普通成员变量被普通成员方法赋值】和【普通代码块】,按在代码中出现的顺序依次执行。

6.执行子类的构造方法。

JVM在搜索类的时候,又是如何判定两个class是相同的呢?

JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。只有两者同时满足的情况下,JVM才认为这两个class是相同的。

就算两个class是同一份class字节码,如果被两个不同的ClassLoader实例所加载,JVM也会认为它们是两个不同class。

类的加载过程,Person person = new Person();为例进行说明。

1).因为new用到了Person.class,所以会先找到Person.class文件,并加载到内存中;

2).执行该类中的static代码块,如果有的话,给Person.class类进行初始化;

3).在堆内存中开辟空间分配内存地址;

4).在堆内存中建立对象的特有属性,并进行默认初始化;

5).对属性进行显示初始化;

6).对对象进行构造代码块初始化;

7).对对象进行与之对应的构造函数进行初始化;

8).将内存地址付给栈内存中的p变量

class实例和class对象的区别

java有两种对象:实例对象和Class对象。

每个类的运行时的类型信息就是用Class对象表示的。它包含了与类有关的信息。

其实我们的实例对象就通过Class对象来创建的

有三种获得Class对象的方式:

  • Class.forName(“类的全限定名”)
  • 实例对象.getClass()
  • 类名.class (类字面常量)

实例newInstance()

最后

看完有什么不懂的可以在评论区问我,觉得对你有帮助的话记得给我点个赞!

还不懂java类加载机制的,建议看下这份阿里技术官总结的笔记!的更多相关文章

  1. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  2. 两道面试题,带你解析Java类加载机制

    文章首发于[博客园-陈树义],点击跳转到原文<两道面试题,带你解析Java类加载机制> 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Gr ...

  3. 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)

    本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...

  4. 深入理解Java类加载机制,再也不用死记硬背了

    谈谈"会"的三个层次 在<说透分布式事务>中,我举例里说明了会与会的差别.对一门语言的学习,这里谈谈我理解的"会"的三个层次: 第一层:了解这门语言 ...

  5. Java类加载机制深度分析

    转自:http://my.oschina.net/xianggao/blog/70826 参考:http://www.ibm.com/developerworks/cn/java/j-lo-class ...

  6. Java类加载机制及自定义加载器

    转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...

  7. Java类加载机制与Tomcat类加载器架构

    Java类加载机制 类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这 ...

  8. 带你解析Java类加载机制

      目录 Java类加载机制的七个阶段 加载 验证 准备(重点) 解析 初始化(重点) 使用 卸载 实战分析 方法论 树义有话说 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如 ...

  9. Java类加载机制以及双亲委派模型

    一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允 ...

随机推荐

  1. 推荐4款个人珍藏的IDEA插件!帮你写出不那么差的代码

    @ 目录 Codota:代码智能提示 代码智能补全 代码智能搜索 Alibaba Java Code Guidelines:阿里巴巴 Java 代码规范 手动配置检测规则 使用效果 CheckStyl ...

  2. Linux入门到放弃之二《目录处理常用命令的使用方法》

    一,目录操作命令 1.用pwd命令查看当前所在的目录: 2.用ls命令列出此目录下的文件和目录: 3.列出此目录下包括隐藏文件在内的所有文件和目录并且长格式显示: (  -l表示长格式,-a表示隐藏文 ...

  3. Vue基础(2)

    fetch与axios请求数据 fetch基本语法: fetch(url,{parmas}).then(res=> res.json()  //返回promise对象 ).then(data=& ...

  4. MFiX-DEM中的并行碰撞搜索

    基于MFiX-19.2.2 DEM并行程序中的颗粒循环 在DEM并行程序中,每个进程只循环该进程包含的颗粒,并且每个进程还有一层ghost cell,用来存放另一个进程发送过来的颗粒信息. 下面添加一 ...

  5. JUC---06线程间通信(二)

    二.线程间定制化调用通信 要使多线程之间按顺序调用,实现A->B->C按顺序输出,使用Lock锁实现,通过Lock锁创建三个Condition实例(三把钥匙),通过不同的条件,调用不同钥匙 ...

  6. SpringBoot整合JPA遇到的问题

    在学习SpringBoot中使用Repository时出现这种错误 或者使用findOne也会报错,只需要改为 应该是SpringBoot版本的原因,fingOne()方法好像已经不用了.

  7. STM32入门系列-STM32时钟系统,STM32时钟树

    时钟对于单片机来说是非常重要的,它为单片机工作提供一个稳定的机器周期从而使系统能够正常运行.时钟系统犹如人的心脏,一旦有问题整个系统就崩溃.我们知道STM32属于高级单片机,其内部有很多的外设,但不是 ...

  8. Spring源码知识概览

    目录 Spring知识总览 1.1 IOC 1.2 Spring中重要接口概览 Spring知识总览 1.1 IOC IOC是控制反转,是一种思想 DI是依赖注入,是控制翻转的一种实现 Spring的 ...

  9. [Luogu P4173]残缺的字符串 ( 数论 FFT)

    题面 传送门:洛咕 Solution 这题我写得脑壳疼,我好菜啊 好吧,我们来说正题. 这题.....emmmmmmm 显然KMP类的字符串神仙算法在这里没法用了. 那咋搞啊(或者说这题和数学有半毛钱 ...

  10. ElasticSearch7.3破解

    破解ES7.3.0到白金版(学习交流使用) 正常安装ELK7.3版本到服务器上 正常部署ELK7到服务器上,先不要启动.然后开始进行破解操作 进行破解操作 需要破解的文件:modules/x-pack ...