附一张图方便理解,一个类的执行过程

类的加载过程,简明的来说


  类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件。在Java中,类装载器把一个类装入JVM中,要经过以下步骤:

  1. 装载:查找和导入Class文件;
  2. 链接:执行校验、准备和解析步骤,其中解析步骤是可以选择的:
    1. 校验:检查载入Class文件数据的正确性;
    2. 准备:给类的静态变量分配存储空间;
    3. 解析:将符号引用转成直接引用;
  3. 初始化:对类的静态变量、静态代码块执行初始化工作。

  类装载工作由ClassLoader及其子类负责,ClassLoader是一个重要的Java执行时系统组件,它负责在运行时查找和装入Class字节码文件。JVM在运行时会产生三个ClassLoader:根装载器、ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器)。其中,根装载器不是ClassLoader的子类,它使用C++编写,因此我们在Java中看不到它,根装载器负责装载JRE的核心类库,如JRE目标下的rt.jar、charsets.jar等。ExtClassLoader和AppClassLoader都是ClassLoader的子类。其中ExtClassLoader负责装载JRE目录ext中的JAR类包;AppClassLoader负责装载ClassPath路径下的类包。

关于这三个ClassLoader的详解博客链接

一、加载


  “加载” 是“类加载”过程的一个阶段。在加载阶段,虚拟机需要完成以下3件事情:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流。
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

  虚拟机规范的这3点要求其实并不算具体,因此虚拟机实现与具体应用的灵活度都是相当大的。

  相对于类加载过程的其他阶段,一个非数组类的加载阶段(准确地说,是加载阶段中获取类的二进制字节流的动作)是开发人员可控性最强的,因为加载阶段既可以使用系统提供的引导类加载器来完成,也可以由用户自定义的类加载器区完成,开发人员可以通过定义自己的类加载器去控制字节流的获取方式(即重写一个类加载器的loadClass()方法)。

  对于数组类而言,数组类本身不通过类加载器创建,它是由Java虚拟机直接创建的。但数组类与类加载器任然有很密切的关系,因为数组类的元素类型最终是要靠类加载器去创建。

  加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式由虚拟机实现自行定义,虚拟机规范未规定此区域的具体数据结构。然后在内存中实例化一个java.lang.Class类的对象(并没有明确规定是在Java堆中,对于HotSpot虚拟机而言,Class对象比较特殊,它虽然是对象,但是存放在方法区里面),这个对象将作为程序访问方法区中的这些类型数据的外部接口。

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

二、验证


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

  Java语言本身是相对安全的语言,使用纯粹的Java代码无法做到注入访问数组边界意外的数据、将一个对象转型为它并未实现的类型、跳转到不存在的代码行之类的事情,如果这样做了,编译器将拒绝编译。

  但前面已经说过,Class文件并不一定要求用Java源码编译而来,可以使用任何途径产生,甚至包括用十六进制编辑器直接编写来产生Class文件。在字节码语言层面上,上述Java代码无法做到的事情都是可以实现的,至少语义上是可以表达出来的。

  虚拟机如果不检查输入的字节流,对其完全信任的话,很可能会因为载入了有害的字节流而导致系统崩溃,所以验证是虚拟机对自身保护的一项重要工作。

三、准备


  准备阶段是正式为类变量分配内存并设置类变量初始值得阶段,这些变量所使用的内存都讲在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。其次,这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量的定义为:

public static int value = 123;

  那变量value在准备阶段过后的初始值为0而不是123,因为这时候尚未开始执行任何Java方法,而把value赋值为123的putstatic指令是程序被编译后,存放于类构造器<clinit>()方法之中,所以把value赋值为123的动作将在初始化阶段才会执行。

四、解析


  解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

五、初始化


  类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码(或者说是字节码)。

  在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit()>方法的过程。

JVM——类的加载过程的更多相关文章

  1. java 反射,类的加载过程以及Classloader类加载器

    首先自定义一个类Person package reflection; public class Person { private String name; public int age; public ...

  2. Java类的加载过程-重点!!

    java类的加载过程有以下几步共同完成: 加载->连接->初始化.连接又分为验证.准备.解析 一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以 ...

  3. 第42天学习打卡(Class类 Class类的常用方法 内存分析 类的加载过程 类加载器 反射操作泛型 反射操作注解)

    Class类 对象照镜子后得到的信息:某个类的属性.方法和构造器.某个类到底实现了哪些接口.对于每个类而言,JRE都为其保留一个不变的Class类型的对象.一个Class对象包含了特定某个结构(cla ...

  4. JAVA - 类的加载过程

    JAVA - 类的加载过程 JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化. 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lang.Class对象 ...

  5. Jvm类的加载机制

    1.概述 虚拟机加载Class文件(二进制字节流)到内存,并对数据进行校验.转换解析和初始化,最终形成可被虚拟机直接使用的Java类型,这一系列过程就是类的加载机制. 2.类的加载时机 类从被虚拟机加 ...

  6. Dubbo源码解析之SPI(一):扩展类的加载过程

    Dubbo是一款开源的.高性能且轻量级的Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用.智能容错和负载均衡,以及服务自动注册和发现. Dubbo最早是阿里公司内部的RPC框架,于 ...

  7. java类的加载过程

    1.类的加载顺序 (1)JVM在首次加载类时会对  静态初始化块.静态成员变量. 静态方法进行一次初始化. (2)只有在调用new方法时才会创建类的实例. (3)对象创建过程: 首先执行父类(如果有) ...

  8. java架构之路-(JVM优化与原理)JVM类的加载机制

    话不多说,先上图. ***.class文件执行大概就是这样来走的.我们都知道我们的java文件经过编译以后会生成对应的class文件.先经过类装载子系统,然后塞进运行时内存模型的元空间,开始执行方法, ...

  9. JVM 类的加载机制

    在对类的实例化之前.JVM 一般会先进行初始化 主要经过如下几个阶段: 1.加载                       类加载的第一阶段,类加载时机有两个: 1.预加载:当虚拟机启动时,会预加载 ...

随机推荐

  1. UVA 11609 Teams 组合数学+快速幂

    In a galaxy far far away there is an ancient game played among the planets. The specialty of the gam ...

  2. amcharts简单封装

    只是简单是封装了一下,目前只能输出线图(折现,圆滑线等),柱状图. 代码如下: ;!function(win,$,AC,undefined){ var DDcharts = function(o){ ...

  3. 矩阵快速幂 POJ 3735 Training little cats

    题目传送门 /* 题意:k次操作,g:i猫+1, e:i猫eat,s:swap 矩阵快速幂:写个转置矩阵,将k次操作写在第0行,定义A = {1,0, 0, 0...}除了第一个外其他是猫的初始值 自 ...

  4. ruby libmysqlclient.18.dylib

    在mac 的rails环境中,如果已经确定安装了 mysql server,但是在启动rails s (服务器)的时候出现  Library not loaded: libmysqlclient.18 ...

  5. iOS开发--成员变量与属性

    属性变量 @interface MyClass:NSObject{ MyObjecct *_object; } @property(nonamtic, retain) MyObjecct *objec ...

  6. 禁用/启用本地连接的dos命令是什么啊?

    运行如下命令:netsh interface show interface 将显示类似下面的画面:Admin State State Type Interface Name ------------- ...

  7. skip-name-resolv

    skip-name-resolve skip-name-resolve 简单解释 MySQL server received a request from you to allow you to co ...

  8. Oracle临时表(Temporary Table)

    GLOBAL TEMPORARY代表全局临时表临时表的元数据存储在数据字典里面 只当第一条DML命令发生的时候才为这张表的段分配空间 临时表数据的可见范围应该是会话级别或是事务级别的 会话或者事务级别 ...

  9. SPOJ 370 Ones and zeros BFS + 同余剪枝

    题意:给一些n,求出最小的只包含0,1的n的倍数 设两数a, b满足: a < b 并且a % n = b % n. 如果 ( a * 10^x + c ) % n = z , 根据同余定理,( ...

  10. git pull使用【转】

    转自:http://www.yiibai.com/git/git_pull.html git pull命令的作用是,取回远程主机某个分支的更新,再与本地的指定分支合并.它的完整格式稍稍有点复杂. $ ...