JVM 类加载

本文详细介绍了JavaClassFile的结构,包括magic、版本、常量池、字节码指令等内容,以及类加载的过程,如加载、验证、准备、解析和初始化。文章还探讨了类加载器的工作原理,特别是双亲委派机制,并提到了运行时的优化策略,如分层编译和方法内联。
摘要由CSDN通过智能技术生成

类文件结构

ClassFile {
	u4 magic;
	u2 minor_version;
	u2 major_version;
	u2 constant_pool_count;  //常量池信息
	cp_info constant_pool[constant_pool_count-1];  //常量池信息
	u2 access_flags;  //访问修饰符
	u2 this_class;
	u2 super_class;
	u2 interfaces_count;  //接口信息
	u2 interfaces[interfaces_count];  //接口信息
	u2 fields_count;  // 类中成员变量
	field_info fields[fields_count];  //类中成员变量
	u2 methods_count;  //类中方法
	method_info methods [methods_count];  //类中方法信息
	u2 attributes_count;   //类的附加属性
	attribute_info attributes[attributes_count];  //类的附加属性
}

magic

0 - 3字节,表示它是否是class类型文件

版本

4 - 7 字节,表示类的版本,52表示Java 8

常量池

8 - 9 字节,表示常量池长度

字节码指令

  • javac 将java文件编译为字节码文件
  • javap -v 反编译class文件

异常

  • 实现原理是异常表
    在这里插入图片描述

语法糖

  • 自动生成默认构造参数
  • 泛型被优化为Object的形式
  • 自动拆装箱是代码优化的形式(不用显示转换)
  • 可变参数被优化为数组的形式
  • foreach对数组循环被编译器优化为fori循环
  • foreach对集合循环被优化为迭代器循环(集合接口继承了迭代器接口)
  • switch结合string分为两阶段switch
    – 首先判断 hashcode,然后判断string是否相等,对byte复制
    – byte 不同的值对应不同的执行
    – hashcode 相同时,增加 if 判断
  • 枚举配合switch是优化为了数组

编译期处理

类加载阶段

加载

连接 - 验证

  • 判断文件是否是java的class文件

连接 - 准备

  • static 修饰的变量申请空间
  • final static 修饰的基本类型,字符串常量申请空间,赋值
  • 未被static final 修饰的变量在构造器中申请空间,赋值

连接 - 解析

  • 将常量池中的符号引用解析为直接引用

初始化

  • 调用构造方法,虚拟机会保证执行过程的线程安全

发生时机

类初始化是懒惰
  • main方法所在的类,首先被初始化
  • 首次访问这个类的静态变量和静态方法时
  • 子类初始化,如果父类还没初始化,会引发
  • 子类访问父类的静态变量,只会触发父类的初始化
  • Class.forname
  • new 会导致初始化
    不会导致类初始化的情况
  • 访问类的 static final 静态变量 (基本类型和字符串)不会触发初始化
  • 类对象的.class 不会触发初始化
  • 类加载器的loadClass方法
  • Class.forname的参数2为false时

类加载器

  1. Bootstrap ClassLoader,无法直接访问,加载JAVA_HOME/jre/lib下的类
  2. Extension ClassLoader,上级为Bootstrap ClassLoader,显示为null,加载JAVA_HOME/jre/lib/ext下的类
  3. Application ClassLoader,上级为Extension ClassLoader,加载classpath下的类
  4. 自定义ClassLoader, 上级为Application ClassLoader,自定义

双亲委派机制加载类

  1. 检查是否已加载
  2. 如果未加载则上级类加载器
  3. 上级类加载器检查是否已加载。如果是 Bootstrap ClassLoader,如果未加载则检查类加载器的加载目录是否存在指定类
  4. 如果上级加载器也没有找到,则检查自身的类加载目录是否有该类
  5. 有则返回,没有就抛异常

实现自定义类加载器

  1. 继承ClassLoader父类
  2. 要遵从双亲委派机制,重写findClass方法
  3. 不是重写loadClass方法,否则不会走双亲委派机制
  4. 读取类的字节码文件
  5. 调用父类的defineClass方法来加载类
  6. 使用者调用该类加载器的loadClass方法

类相同的条件

  1. 类加载器相同
  2. 包名相同
  3. 类名相同

运行期优化

分层编译

  • 解释器,将字节码编译为通用的机器码
  • 解释器即使下次遇到相同的机器码仍然会重复执行
  • JIT,将字节码编译为平台特定的机器码
  • JIT会将翻译的机器码存入Code Cache,下次遇到相同的字节码,直接执行,无需编译

方法内联

反射优化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值