[jvm学习笔记]-类加载过程

JVM类加载的过程

加载=>验证=>准备=>解析=>初始化 5个阶段所执行的具体动作

加载

在加载阶段,虚拟机需要完成3个事情
1.通过一个类的全限定名获取定义此类的二进制字节流
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3.在内存中生成一个代表这个类的 java.lang.class 对象,作为方法区这个类的各种数据的访问入口

相对于类加载过程的其他阶段,一个非数组类(数组类是由jvm虚拟机直接创建的)的加载过程(加载阶段获取类的二进制字节流的动作)是开发人员可控性最强的,因为加载阶段可以使用系统提供的引导类加载器去完成,也可以有开发人员自定义的类加载器去完成,开发人员可以通过定义自己的类加载器去控制字节流的获取方式(重写一个类加载器的loadClass()函数)。

加载阶段和连接阶段的部分内容是交叉进行的(如一部分字节码文件的验证动作),加载阶段尚未完成,连接阶段可能已经开始,但是这些夹在加载阶段进行之中的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持固定的先后顺序。

验证

验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自己的安全。

java语音本身是相对安全的语音,如果遇到异常代码(指无法通过语法检查的代码),编译器是拒绝编译的,但是所有Class文件并不一定是按照java源码编译来的,甚至可以用十六进制编辑器直接修改产生的Class文件,虚拟机如果不检查输入的字节流,而对其完全信任的话,可能载入了有害的字节流而导致系统崩溃,这是我们无法接受的,所以验证是虚拟机对真身保护的一项重要工作

验证阶段大致上会完成下面4个检验动作:文件格式验证,元数据验证,字节码验证,符号引用验证

1.文件格式验证
第一阶段要验证字节流是否符合Class文件格式规范,并且能被当前版本的虚拟机处理。
2.元数据验证
第二阶段是对字节码描述的信息进行语义化分析,以保证其描述的信息符合java语音规范的要求。
3.字节码验证 第三阶段是整个验证过程中最复杂的阶段,主要是通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的。这个阶段会对类的方法体进行校检分析,确保在方法运行的时候不能做出危害虚拟机安全的时间。
4.符号引用验证 最后一个阶段的校检发送在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接阶段的第三个阶段,解析阶段中发生。

准备

准备阶段是正式为类变量分配内存并设置为初始值的阶段(该阶段仅将变量设置为初始值,而并非赋值),这些变量所使用的内存都将在方法区中进行分配,这个时候进行的内存分配的仅包括类变量(static修饰的变量),而不包括实例变量,实例变量将会在对象实例化的时候随着对象一起分配在java堆中。而且这里所说的初始化通常指数据类型的零值。

解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,主要包括四种类型引用的解析。类或接口的解析、字段解析、方法解析、接口方法解析。

java会编译(类似编译过程)会把类文件(.java)编译成class文件(.class),但是这个过程中如果A类需要引用B类,由于没有加载入内存执行,所以他并不知道B类的地址,因此用符号代替,即为符号引用。到执行程序时会加载类,相关类会进入内存,因此可以就有了内存地址,A类就可以将符号引用映射带B类地址,就是直接引用了!

初始化

类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段开发人员可以用自定义类加载 器参与之外,其他动作都是有虚拟机主导和控制的,到了初始化阶段,才真正开始执行类中定义的java程序代码。
在准备阶段,变量已经付过一次初始值,而在初始化阶段,则根据程序员的代码来进行赋值,初始化阶段是执行类的构造器赋值的。这些资源有static{}块,构造函数,父类的初始化等。

至于使用和卸载阶段阶段,这里不再过多说明,使用过程就是根据程序定义的行为执行,卸载由GC完成。
时间: 2024-10-07 22:37:28

[jvm学习笔记]-类加载过程的相关文章

JVM学习笔记:虚拟机的类加载机制

JVM类加载机制分两部分来总结: (1)类加载过程 (2)类加载器 一.JVM类加载过程 类的加载过程:加载 →连接(验证 → 准备 → 解析)→ 初始化. 类的生命周期:加载 →连接(验证 → 准备 → 解析)→ 初始化 → 使用 →  卸载. 1 加载 1.1 加载阶段要做的3件事情 通过一个类的全限定名来获取该类对应的二进制字节流. 将这个字节流所代表的静态存储结构转化为方法区的数据结构. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

JVM 学习笔记

JVM  ----Java  Virtual Machine   (熟称:JAVA虚拟机),JVM 在执行JAVA程序的过程中将内容划分为若干个区域,其有各自的用途和管理机制.如下图: 1.  程序计算器(Program Counter Register)  --  是当前线程所执行字节码的行号指示器,通过改变其值来实现执行不同的代码指令.内存占用小,线程私有,支持多线程处理(多线程时,每个线程有一个独立程序计算器,已达到各自互不影响), 也正是由于这些特点,该区域是JVM规范中唯一没有规定任何

java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessController的checkPerssiom方法,访问控制器AccessController的栈检查机制又遍历整个 PerssiomCollection来判断具体拥有什么权限一旦发现栈中一个权限不允许的时候抛出异常否则简单的返回,这个过程实际上比我的描述要复杂 得多,这里我只是简单的一句带过,因为这

java之jvm学习笔记五(实践写自己的类装载器)

java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类装载器和安全管理器是可以被动态扩展的,或者说,他们是可以由用户自己定制的,今天我们就是动手试试,怎么做这部分的实践,当然,在阅读本篇之前,至少要阅读过笔记三. 下面我们先来动态扩展一个类装载器,当然这只是一个比较小的demo,旨在让大家有个比较形象的概念. 第一步,首先定义自己的类装载器,从Clas

JVM学习笔记-内存管理

第一章 内存分配 1. 内存区域. 方法区和堆(线程共享),程序计数器 , VM栈 和 本地方法栈(线程隔离). 1) java虚拟机栈:线程私有.描述的是java方法执行的内存模型:栈帧,用户存储 局部变量表,操作数栈,动态链接,方法出口等信息. 局部变量表在编译时即可完全确定!如果线程请求的栈深度大于 规定的深度,StackOverflowError. 2) 本地方法栈,类似. 3)堆:垃圾收集器管理的主要区域.线程共享. 4)方法区: 各个线程共享.存储:加载的类信息,常量,静态变量,即时

Java虚拟机JVM学习05 类加载器的父委托机制

Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap) 扩展类加载器(Extension) 系统类加载器(System) 2.用户自定义的类加载器: java.lang.ClassLoader的子类,用户可以定制类的加载方式. JVM自带的加载器 Java虚拟机自带了以下几种加载器. 1.根(Bootstrap)类加载器: 该加载器没有父加载器. 它

JVM学习笔记(一)------基本结构

从Java平台的逻辑结构上来看,我们能够从下图来了解JVM: 从上图能清晰看到Java平台包括的各个逻辑模块,也能了解到JDK与JRE的差别 对于JVM自身的物理结构,我们能够从下图俯视一下: 对于JVM的学习,在我看来这么几个部分最重要: Java代码编译和运行的整个过程 JVM内存管理及垃圾回收机制 以下将这两个部分进行具体学习 JVM学习笔记(一)------基本结构,布布扣,bubuko.com

java之jvm学习笔记十三(jvm基本结构)

java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成图形,所以只要你有耐心,仔细,认真,并发挥你的想象力,这一章之后你会充满自信.当然,不是说看完本章,就对jvm了解了,jvm要学习的知识实在是非常的多.在你看完本节之后,后续我们还会来学jvm的细节,但是如果你在学习完本节的前提下去学习,再学习其他jvm的细节会事半功倍. 为了让你每一个知识点都有迹

JVM学习笔记(四)------内存调优【转】

转自:http://blog.csdn.net/cutesource/article/details/5907418 版权声明:本文为博主原创文章,未经博主允许不得转载. 首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM. 对JVM内存的系统级的调优主要的目的是减少GC的频率和Fu