还不懂java类加载机制的,建议看下这份阿里技术官总结的笔记!
类加载机制
把class文件加载到内存,并对数据进行校验,准备,解析,初始化,形成可以被虚拟机直接使用的字节码
类加载的时机(触发类的初始化)
- 使用new关键字实例化对象
- 读取一个类的静态代码块
- 使用java.lang.reflect包的方式对类进行反射调用
类加载过程
整个生命周期包括:加载、校验、准备、解析、初始化、使用和卸载7个阶段。
- 加载:通过一个类的全限定名来获取定义此类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,在内存中生成一个代表这个类的Class对象,作为方法区这个类的各种数据的访问入口
- 校验:校验是连接阶段的第一步,这一阶段的目的是确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟自身的安全。
- 准备:准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法去中进行分配。这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。
- 解析:解析阶段是虚拟机将常量池内的符号(Class文件内的符号)引用替换为直接引用(指针)的过程。
- 初始化:初始化阶段是类加载过程的最后一步,开始执行类中定义的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类加载机制的,建议看下这份阿里技术官总结的笔记!的更多相关文章
- 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制
你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...
- 两道面试题,带你解析Java类加载机制
文章首发于[博客园-陈树义],点击跳转到原文<两道面试题,带你解析Java类加载机制> 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Gr ...
- 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)
本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...
- 深入理解Java类加载机制,再也不用死记硬背了
谈谈"会"的三个层次 在<说透分布式事务>中,我举例里说明了会与会的差别.对一门语言的学习,这里谈谈我理解的"会"的三个层次: 第一层:了解这门语言 ...
- Java类加载机制深度分析
转自:http://my.oschina.net/xianggao/blog/70826 参考:http://www.ibm.com/developerworks/cn/java/j-lo-class ...
- Java类加载机制及自定义加载器
转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...
- Java类加载机制与Tomcat类加载器架构
Java类加载机制 类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这 ...
- 带你解析Java类加载机制
目录 Java类加载机制的七个阶段 加载 验证 准备(重点) 解析 初始化(重点) 使用 卸载 实战分析 方法论 树义有话说 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如 ...
- Java类加载机制以及双亲委派模型
一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允 ...
随机推荐
- C# 面试前的准备_基础知识点的回顾_01
本系列本章来至于http://www.cnblogs.com/LionelMessi/p/4311931.html 1.try{} 里面有个Return语句,那么紧跟try后面的Finally{}会不 ...
- swagger使用随笔
2020-10-21 在一技术群里看到有个大佬想用 swagger 实现个功能:基础 Api 项目中写好通用的接口,配置好 swagger .上级项目直接引用项目,就能访问 swagger 起来用.相 ...
- java: 非法字符: '\ufeff'
错误问题记录: Error:(1, 1) java: 非法字符: '\ufeff' Error:(1, 1) 错误: 需要class, interface或enum报错 问题发生时因为编码问题导致,如 ...
- Rust借用机制的理解分析
Rust初学者大多会遇到这样的问题: 为什么同一资源不可被同时可变借用和不可变借用? 为什么Rc一定只能是只读的,一定要配合std::cell系列(Cell,RefCell,UnsafeCell)才能 ...
- poj1050 To the Max(降维dp)
To the Max Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 49351 Accepted: 26142 Desc ...
- 如果只推荐一本 Python 书,我要 Pick 它!
今年二月初,我偶然看到了一条推特: <流畅的Python>一书的作者发布了一条激动人心的消息:他正在写作第二版! 如果要票选最佳的 Python 进阶类书目,这本书肯定会是得票率最高的书籍 ...
- 在Linux上成功启动Jenkins却无法访问的问题
本鸟最近打算学习Jenkins,正准备在Linux上面鼓捣一番,,却没想被入门级别问题当头一棒 下载完jenkins.war,使用java -jar命令在8088端口开启服务:java -jar je ...
- 干货分享:一键网络重装系统 - 魔改版(适用于Linux / Windows)
简介 一键网络重装系统 - 魔改版,它可以通过Internet重新安装Linux和Windows以及常见的操作系统.例如:Linux(CentOS,Debian,Ubuntu.etc..),Win ...
- STM32入门系列-介绍STM32型号与功用
作为STM32初学者,一般会选择购置一块开发板,因为在开发板上有很多已经集成好的模块,如红外模块.按键模块.LED模块.DAC模块.ADC模块.can模块.485模块.以太网模块.WiFi模块.蜂鸣器 ...
- 使用MQTT协议的4G DTU模块具有什么优势
什么是MQTT协议 要了解使用MQTT协议的4G DTU模块具有哪些优势,首先我们需要了解什么是MQTT协议,MQTT协议最早是IBM开发的一个即时通讯协议,它的主要是为大量计算能力有限且工作在低带宽 ...