Java类加载过程

1. 什么是类加载过程

  • 类加载过程就是将.class文件中类的元信息加载进内存,创建Class对象并进行解析、初始化类变量等的过程

  • 类加载一共分为以下三个阶段 [ 装载, 链接, 初始化 ]

  • JVM并不是一开始就会将所有的类加载到内存,而是用到某个类,才会去加载,只加载一次,后续会说到类的加载时机

1.1 loading

类的装载主要的职责为

  • 通过类的全名将.class文件的二进制字节流读入内存(JDK1.7及之前为JVM内存,JDK1.8及之后为本地内存)
  • 解析类的二进制数据流为方法区的数据结构 (类模板-反射机制就是基于这一基础所诞生的)
  • 并在堆内存中为之创建Class对象,作为.class进入内存后的数据的访问入口。
    类加载

拓展

  • 在这里只是读入二进制字节流,后续的验证阶段就是要拿二进制字节流来验证.class文件,验证通过,才会将.class文件转为运行时数据结构

  • 在JDK1.7及以前,Hot Spot JVM(普遍在用的JVM)存在一块叫做方法区的内存,也称之为永久代,这块区域用于存放类的元数据信息,包括类的字段,版本,方法等,这块区域,可以理解为.class文件进入内存后的位置。在JDK1.8,取消了方法区,取而代之的是元数据区,该元数据区并非JVM内存,而是本地内存。此外在JDK1.7时,将常量池从方法区移除,在堆内存开辟了一块空间作为常量池,有人说这是为取消方法区做的准备

  • 为何取消方法区?
    官方说法为:移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代
    现实使用中存在问题:方法区存储类的元数据信息,我们不清楚一个程序到底有多少类需要被加载,且方法区位于JVM内存,我们不清楚需要给方法区分配多大内存,太小容易PermGen OOM,太大,在触发Full GC时又极其影响性能,同时还存在一些内存泄露的问题

1.2 linking

链接阶段有三个步骤

1.2.1 验证

该阶段主要是为了保证加载进来的字节流符合JVM的规范,不会对JVM有安全性问题。其中有对元数据的验证,例如检查类是否继承了被final修饰的类;还有对符号引用的验证,例如校验符号引用是否可以通过全限定名找到,或者是检查符号引用的权限(private、public)是否符合语法规定等。

1.2.2 准备

准备阶段的主要任务是为类的静态变量开辟空间并赋默认值

  • 静态变量是基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0
  • 静态变量是引用类型的,默认值为null
  • 静态常量默认值为声明时设定的值
    例如:public static final int i = 3; 在准备阶段,i的值即为3
1.2.3 解析

该阶段的主要职责为将Class在常量池中的符号引用转变为直接引用,此处针对的是静态方法及属性和私有方法与属性,因为这类方法与私有方法不能被重写,静态属性在运行期也没有多态这一说,即在编译器可知,运行期不可变,所以适合在该阶段解析,譬如类方法main替换为直接引用,为静态连接,区别于运行时的动态连接(后续我会写关于JVM内存结构的文章,在讲解栈帧时会介绍动态链接)。

  • 符号引用即字符串,说白了可以是一个字段名,或者一个方法名;
  • 直接引用即偏移量,说白了就是类的元信息位于内存的地址串,例如,一个类的方法为test(),则符号引用即为test,这个方法存在于内存中的地址假设为0x123456,则这个地址则为直接引用。

1.3 initialization

topic : 在前两个阶段并未执行到代码, 而在初始化阶段开始执行代码了

初始化阶段主要任务

  1. 给静态变量显示赋值 (注意链接阶段的准备环节是赋初值 0这个要区别开)
  2. 静态代码块里的变量显示赋值

拓展

  • 在初始化阶段, 如果有声明静态变量或静态代码块中的变量并且显式赋值了的话, 就会调用<clinit>()方法来初始化这些变量, 并且<clinit>()方法是加了锁的会产生死锁现象

  • 区分<clinit>() 和 <init>()
    <init>() 方法在调用某个类的构造方法是调用, 并且会把不是静态的都执行一遍并且 执行顺序优先于构造方法
    <clinit>() 方法在类的初始化阶段时(如果有静态变量并且显示赋值)则会调用该方法, 把静态变量的赋值操作以及静态代码块都会执行一遍

2. 类加载的时机

主动使用

被动使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值