java虚拟机原理:类加载过程详解

目录
  • 一、Java 类加载过程
    • 1、字节码编译
    • 2、加载
    • 3、连接
    • 4、初始化
  • 总结

一、Java 类加载过程

1、字节码编译

编写好 Java 源码 Student.java ,

使用 javac 将上述 Java 源码编译成 Class 字节码文件 Student.class ,

2、加载

加载 : 通过 " 类加载子系统 " 将该字节码文件 , 加载到 Java 虚拟机内存中 的 方法区 , 然后开始执行 " 连接 " 操作 ,

类加载时机 : Java 程序执行时 , 并不是一开始将所有的字节码文件都加载到内存中 , 而是用到时才进行加载 ;

  • 通过 new 关键字创建实例对象 ;
  • 通过 Class 反射 获取类 ;
  • 如 : Class.forName(“Xxx”) 获取类 ;
  • 序列化 / 反序列化 ;
  • 调用 clone 克隆对象 ;
  • 有 main 函数的类 , 会默认自动加载 ;
  • 调用子类 , 如果之前没有加载过父类 , 则 自动加载父类 ;

3、连接

连接操作 分为 3 3 3 个步骤 :

  • 验证 : 对 字节码文件 进行校验 , 查看该字节码格式是否正确 , 如 : 是否以 0xCAFEBABE 开头 , 字段表 , 方发表 , 属性表 等格式是否正确 , 进行校验 ;
  • 校验示例 : 假设校验如下字节码数据 , 原始数据是 【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 ) 二、字节码文件示例 章节中的 Java 源码 , Class 字节码 , 字节码附加信息 ;

在 Student 构造方法中 , 会调用到 1: invokespecial #1 父类构造方法 , 如果父类有有参的构造方法且没有声明无参构造方法 , 子类必须实现一个相同参数的构造方法 , 否则就会报错 ;

Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
{
  public Student();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
}
  • 准备 : 在该阶段 , 在 方法区 中 , 为 类中的静态变量 进行内存划分 , 并对这些静态变量进行 默认值赋值 , 一般赋值 0 , null 等默认值 ; 即使静态变量 static int a = 5 已经有了赋值 , 但是在该阶段暂时给该静态变量赋值 0 ;
  • 解析 : 将 " 常量池 " 中的 " 符号引用 " 转为 " 直接引用 " ;

符号引用 : 下面就是 常量池中的 符号引用 , 引用是 以符号的形式表示出来 的 , 这并不是内存中的引用 ; 直接引用 是 将 #1 = Methodref #4.#17 样式的 符号引用 转为 指向内存地址 的 指针引用 ; JVM 线程栈 的 栈帧 中的 动态链接 , 就是持有的一个指向内存的指针 , 该指针指向 栈帧 对应方法 在运行时 常量池中的 内存地址 ; 该内存地址是在 方法区 中的 ;

Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#18         // Student.name:Ljava/lang/String;
   #3 = Class              #19            // Student
   #4 = Class              #20            // java/lang/Object

( 分析的数据是 【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 ) 二、字节码文件示例 章节中的 Java 源码 , Class 字节码 , 字节码附加信息 ; )

4、初始化

初始化 : 对变量进行 指定赋值 ;

如 : 有静态变量 static int a = 5 , 在 连接 过程中的 准备 阶段 , 为该变量赋值默认值 0 ; 在 初始化 阶段 , 为其赋值 代码 中设置的真正的 指定初始值 5 ;

总结

借助下图理解类加载过程 ;

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的等多内容!

(0)

相关推荐

  • Java类加载的过程详解

    目录 Java:类加载过程 1.加载--3件事 2.连接 2.1.验证 2.2.准备 2.3.解析 3.初始化 总结 Java:类加载过程 1.加载--3件事 1.通过全类名获取定义此类的二进制字节流(eg:从jar.war中获取): 2.将字节流所代表的静态存储结构转换为方法区的运行时数据结构: 3.在内存中生成一个代表该类的Class对象,作为方法区这些数据的访问入口. 2.连接 加载阶段和连接阶段的部分内容是交叉进行的,加载尚未结束,连接阶段可能就开始运行了. 2.1.验证 2.2.准备

  • 分析Java中的类加载问题

    目录 一.Java类的加载顺序 二.类加载过程 三.被动引用中和类静态初始化的关系 四.类加载器双亲委派 一.Java类的加载顺序 引用1个网上的经典例子,并做稍许改动,以便大家更好地理解. public class Animal { private int i = test(); private static int j = method(); static { System.out.println("a"); } Animal(){ System.out.println("

  • Java tomcat中的类加载器和安全机制你了解吗

    目录 类加载器 双亲委派 URLClassLoader Tomcat中类加载器架构 安全机制 总结 类加载器 java中的类并不是一次加载完成的,而是按需加载.类加载器是用于加载java类到java虚拟机中的组件,它负责读取java字节码,并转换成 java.lang.Class 的一个实例,使字节码.class文件可以运行.一般类加载器负责根据一个指定的类找到对应的字节码,然后根据这些字节码定义一个java类.另外,它还可以加载资源,包括图像文件和配置文件. 类加载器可以使java类动态地加载

  • Java虚拟机之类加载

    一.类加载流程 类加载的流程可以简单分为三步: 加载 连接 初始化 而其中的连接又可以细分为三步: 验证 准备 解析 下面会分别对各个流程进行介绍. 1.1 类加载条件 在了解类接在流程之前,先来看一下触发类加载的条件. JVM不会无条件加载类,只有在一个类或接口在初次使用的时候,必须进行初始化.这里的使用是指主动使用,主动使用包括如下情况: 创建一个类的实例的时候:比如使用new创建,或者使用反射.克隆.反序列化 调用类的静态方法的时候:比如使用invokestatic指令 使用类或接口的静态

  • 深入探究Java中的类加载机制

    目录 前言 步入正题 类的加载过程: 1.加载 2.验证 3.准备 4.解析 5.初始化 类加载器 源码 总结 前言 学生时代应抱着问题去学习一门语言,例如:在学习java语言的过程中,我遇到过java主方法main里面参数到底是存的什么?还有java语言的Object是如何成为所有类的父类的?java虚拟机到底如何解析字节码文件的?java是纯面向对象编程语言那么它的类是怎样的加载过程?今天我就带着大家一探究竟. 步入正题 首先我们都熟悉DOS界面去执行我们编写的源码,第一步使用javac x

  • Java之类加载机制案例讲解

    1.类加载 <1>.父子类执行的顺序 1.父类的静态变量和静态代码块(书写顺序) 2.子类的静态变量和静态代码块(书写顺序) 3.父类的实例代码块(书写顺序) 4.父类的成员变量和构造方法 5.子类的实例代码块 6.子类的成员变量和构造方法 <2>类加载的时机 如果类没有进行初始化,则需要先进行初始化,虚拟机规范则是严格规定有且只有5种情况必须先对类进行初始化(而加载,验证,准备要在这个之前开始) 1.创建类的实例(new的方式),访问某个类的静态变量,或者对该静态变量赋值,调用类

  • java虚拟机原理:类加载过程详解

    目录 一.Java 类加载过程 1.字节码编译 2.加载 3.连接 4.初始化 总结 一.Java 类加载过程 1.字节码编译 编写好 Java 源码 Student.java , 使用 javac 将上述 Java 源码编译成 Class 字节码文件 Student.class , 2.加载 加载 : 通过 " 类加载子系统 " 将该字节码文件 , 加载到 Java 虚拟机内存中 的 方法区 , 然后开始执行 " 连接 " 操作 , 类加载时机 : Java 程序

  • java 虚拟机中对象访问详解

    java 虚拟机中对象访问详解 对象访问会涉及到Java栈.Java堆.方法区这三个内存区域. 如下面这句代码: Object objectRef = new Object(); 假设这句代码出现在方法体中,"Object objectRef" 这部分将会反映到Java栈的本地变量中,作为一个reference类型数据出现.而"new Object()"这部分将会反映到Java堆中,形成一块存储Object类型所有实例数据值的结构化内存,根据具体类型以及虚拟机实现的

  • Java Linkedlist原理及实例详解

    这篇文章主要介绍了Java Linkedlist原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 定义:linkedlist属于链表结构,方便添加和删除元素,但查询不方便,适用于对收尾的操作. 具有具体的对象,使用对象调用具体的方法 add // 添加元素 //在中间添加元素 arr.add("H"); addFirst:在集合最前面添加元素 // 在链表头部添加元素 arr.addFirst("F")

  • java转换时区时间过程详解

    这篇文章主要介绍了java转换时区时间过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一丶时区 由于世界各国家与地区经度不同,地方时也有所不同,因此会划分为不同的时区. 地球是自西向东自转,东边比西边先看到太阳,东边的时间也比西边的早.东边时刻与西边时刻的差值不仅要以时计,而且还要以分和秒来计算,这给人们带来不便. 为了克服时间上的混乱,1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区(东.西

  • Java搭建RabbitMq消息中间件过程详解

    这篇文章主要介绍了Java搭建RabbitMq消息中间件过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 当系统中出现"生产"和"消费"的速度或稳定性等因素不一致的时候,就需要消息队列. 名词 exchange: 交换机 routingkey: 路由key queue:队列 控制台端口:15672 exchange和queue是需要绑定在一起的,然后消息发送到exchange再由exchange通过ro

  • Java Servlet响应httpServletResponse过程详解

    目录 一.核心方法 1.setStatus 2.setHeader(Stringname,Stringvalue) 3.addHeader(Stringname,Stringvalue) 4.setContentType(Stringtype) 二.响应一个网页 三.返回一个文件 四.返回json数据 一.核心方法 1.setStatus 设置响应状态码 如果没有调用这个方法,默认返回200状态码(前提:正常执行,没有异常) 如果出现异常,返回500 前端代码: <body> <h3&g

  • Java虚拟机内存区域划分详解

    在谈 JVM 内存区域划分之前,我们先来看一下 Java 程序的具体执行过程,我画了一幅图. Java 源代码文件经过编译器编译后生成字节码文件,然后交给 JVM 的类加载器,加载完毕后,交给执行引擎执行.在整个执行的过程中,JVM 会用一块空间来存储程序执行期间需要用到的数据,这块空间一般被称为运行时数据区,也就是常说的 JVM 内存. 所以,当我们在谈 JVM 内存区域划分的时候,其实谈的就是这块空间--运行时数据区. 大家应该对官方出品的<Java 虚拟机规范>有所了解吧?了解这个规范可

  • java内部类原理与用法详解

    本文实例讲述了java内部类原理与用法.分享给大家供大家参考,具体如下: 概念 内部类:可以包含在另外一个类中的类 外部类:包含内部类的类 每个内部类都会被编译为一个独立的类,生成一个独立的字节码文件. 内部类可以方便地访问外部类的私有变量,内部类也可以声明为private从而实现对外完全隐藏. 分类 java中的四种内部类(根据定义的位置和方式划分) -静态内部类 -成员内部类 -方法内部类 -匿名内部类 分类介绍 -静态内部类 特征:在类的内部中存在另一个类,且该类被static修饰 使用范

  • Java匿名内部类原理与用法详解

    本文实例讲述了Java匿名内部类原理与用法.分享给大家供大家参考,具体如下: 一 点睛 匿名内部类适合创建那种只需要一次使用的类,定义匿名内部类的语法格式如下: new 父类构造器(实参列表) | 实现接口() { //匿名内部类的类体部分 } 从上面的定义可以看出,匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口. 两条规则. 匿名内部类不能是抽象类. 匿名内部类不能定义构造器.由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以初始化块,可以通过初始

  • Java操作Zookeeper原理及过程详解

    ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分布式协调/通知.集群管理.Master 选举.分布式锁和分布式队列等功能. Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心. 服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据.如

随机推荐