深圳 电子商务网站开发,毕业设计网站建设流程,网站建设和客户面谈,网站都需要什么类别一、背景
Java代码被编译器变成生成Class字节码#xff0c;但字节码仅是一个特殊的二进制文件#xff0c;无法直接使用。因此#xff0c;都需要放到JVM系统中执行#xff0c;将Class字节码文件放入到JVM的过程#xff0c;简称类加载。
二、整体流程 三、阶段逻辑分析
3…一、背景
Java代码被编译器变成生成Class字节码但字节码仅是一个特殊的二进制文件无法直接使用。因此都需要放到JVM系统中执行将Class字节码文件放入到JVM的过程简称类加载。
二、整体流程 三、阶段逻辑分析
3.1 加载Loading
3.1.1 字节码来源
由于类的Class二进制字节码来源可能不同JVM在此处做了扩展通过类的全限定名来加载不同来源的二进制字节码文件。以下是一些可能的来源
本地文件中获取网络上获取压缩包中获取加密文件中获取运行时内存中获取。例如使用动态代理技术时进行字节码重组最终生成的二进制字节流就会在内存获取。
3.1.2 加载步骤
【步骤1】:通过类的全限定名获取类的二进制字节流 【步骤2】将二进制字节码中的静态存储结构转化为方法区的运行时数据结构同时在方法区会生成InstanceKlass对象。下面详细讲解一下字节码文件 字节码的组成
一般信息
1. 魔数
2. 字节码文件对应的Java版本号
3. 访问标识用于区分类、接口、枚举或注解等类型
4. 子类、父类和接口的索引用于找到子类、父类或结构的信息。索引指的在常量池中的位置常量池
1. 字符串常量
2. 类、接口名或字段名
其中的 #数字 即符号引用表示在常量池中的位置。从图中可以看出有String_info,Class_info,Methodref_info等信息字符串常量池仅是其中的一小部分。字段当前类或接口声明的字段信息
方法当前类或接口声明的方法信息
属性类的属性【步骤3】在内存【堆中】中生成一个当前类的Class对象作为访问方法区的入口。
疑问为什么有了InstanceKlass对象还需要Class对象
1.InstanceKlass对象是C语言生成的对象因此Java代码无法直接操作InstanceKlass对象
2.Klass对象中不仅包含类的基本信息还包括虚方法表信息。虚方法表信息是给Java虚拟机使用的,开发者没有权限使用因此创建一个简单的Class对象给开发者使用这样Java虚拟机就能很好的控制开发者访问数据的范围3.2 链接Linking
3.2.1 验证
文件格式验证、元数据信息验证、字节码正确性验证以及符号引用存在性验证。3.2.2 准备 static final修饰的基本变量进行显示初始化赋值。【隐士初始化在编译器阶段已经完成】static 修饰的变量分配内存空间并进行隐士初始化赋值。JDK7放在方法区中JDK8放在堆中。 3.2.3 解析
编译阶段由于尚未加载到内存并不知道实际的内存引用关系仅是通过特殊方式#数字将具有引用关系的属性记录下来最终形成符号引用 运行阶段各种属性已经被分配过内存空间了因此它们有实际的内存地址。此时根据符号引用将属性之间的引用关系转化为内存地址的实际引用关系最终变成直接引用。
3.3 初始化Init
主要是编译器自动收集类中所有的静态变量以及静态代码块赋值动作生成clinit方法按照代码赋予的值进行赋值。编译器收集的顺序主要是语句在代码中出现的顺序决定的。 触发类的初始化的几种方式
1. 访问一个类的静态变量或静态方法但若变量是final修饰且等号右边是常量的不会触发初始化
2. 调用Class.forName(String className)方法;
3. 通过new 创建对象;
4. 执行Main方法的当前类无法触发类的初始化的几种方式
1. 无静态代码块且无静态赋值语句;
2. 仅有静态变量的声明无赋值操作;
3. 静态变量的定义使用final修饰父子类的初始化规则
1. 直接访问父类的静态变量,不会触发子类的初始化;
2. Java虚拟机保证子类的clinit方法执行之前父类的clinit一定已经执行完毕所以父类中的静态变量和静态代码块是优先于子类的静态变量和静态代码块执行的3.4 使用和卸载
使用表示当前类正在被使用 卸载表示已经被垃圾回收