每天进步一点点!

今天我们一起看一下类加载的准备阶段和解析阶段。

先看一下准备阶段:主要任务是在方法区中为类变量(仅static修饰变量,不包含实例变量)分配内存并设置类变量初始化的阶段。

这里面的区别,我们通过下面的代码来简单了解一下。

我们将上面的代码编译好后,通过字节码工具看一下其中的信息。

首先,从上图可以看出,被final修饰的b是直接赋值的。

我们再打开classlib,如下图所示,b对应的是一个ConstantValue常量,而不是一个引用,对应的,在准备阶段,虚拟机就会将常量值2赋给b。

而对于只有static修饰的变量a,在准备阶段,将初始化为0。如下图所示,在执行构造器方法clinit()的时候才会把把1复制给a。

到了变量c这里,则又不一样。它在准备阶段是不会进行任何操作的。如下图所示,到了对象构造方法init()中,才会把值3赋给c。

类的普通变量在对象初始化的时候随着对象分配到Java堆中。

下面再看一下解析阶段:虚拟机的主要任务是将常量池内的符号引用替换为直接引用。

前面也已经提过了引用的概念,这里让我们再复习一下(以下概念引自《深入理解Java虚拟机》)。

符号引用(Symbolic References):以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。

直接引用(Direct References):直接引用可以是直接指向目标的指针、相对偏移量或是一个能直接定位到目标的句柄。

另外,符号引用的的目标不一定已经加载到内存中,而直接引用的目标必然已经加载到内存中。

以上是对这两种引用的定义,笔者谈一下自己的理解。

对于虚拟机能直接使用的类型,比如基本数据类型的char,int,long,double等定义的变量引用,都是直接引用,比如定义变量int a = 1。

而当变量的引用指向一个类的时候,比如定义Test test = new Test(),jvm只会存储这个类对应的符号com.xkx.test.Test,而不会存储具体的类信息,这就是符号引用。

掌握了引用的概念之后,其实解析就比较简单了,下面简单地了解一下。

需要解析的内容包含以下四个部分:

1、类或接口的解析

2、字段解析

3、类方法解析

4、接口方法解析

以类或接口的解析为例,包含以下三个步骤:

1. 如果该符号引用不是一个数组类型,那么虚拟机将会把该符号代表的全限定名称传递给调用这个符号引用的类。这个过程由于涉及验证过程所以可能会触发其他相关类的加载。

2. 如果该符号引用是一个数组类型,并且该数组的元素类型是对象。我们知道符号引用是存在方法区的常量池中的,该符号引用的描述符会类似”[java/lang/Integer”的形式,将会按照上面的规则进行加载,虚拟机将会生成一个代表此数组对象的直接引用。

3. 如果上面的步骤都没有出现异常,那么该符号引用已经在虚拟机中产生了一个直接引用,但是在解析完成之前需要对符号引用进行验证,主要是确认当前调用这个符号引用的类是否具有访问权限,如果没有访问权限将抛出java.lang.IllegalAccess异常。

剩下的部分解析步骤和类与接口的解析步骤大同小异,这里就不再赘述了,有兴趣的可以自行百度一下。

另外,有一点需要提一下,除invokedynamic指令以外,虚拟机会对第一次解析结果进行缓存,记录解析状态,避免重复解析。

今天的学习就到这里了,笔者认为初始化阶段是比较贴近于实际的内容,下一篇将单独整理出来和大家来分享。

喜欢文章或想一起学习的朋友可以关注我,给我点赞,我将会持续更新,有什么疑问或文中有不当之处请给我留言,真诚地希望能与大家一起交流探讨,学习进步。

java 准备 解析_深入理解JAVA虚拟机学习笔记24——类加载的准备和解析相关推荐

  1. java 调用弗雷_深入理解java虚拟机(十一) 方法调用-解析调用与分派调用

    [方法调用并不等同于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程.在程序运行时,进行方法调用是最普 方法调用过程是指确定被调用方法的 ...

  2. java 常量折叠_深入理解Java虚拟机之早期编译器优化

    Javac编译器 Javac编译器是一个由Java语言编写的程序 Javac的源码与调试 从Sun Javac的代码来看,编译器大致分为3个过程: 解析与填充符号表的过程 插入式注解处理器的注解处理过 ...

  3. java事件处理模型_从零开始理解JAVA事件处理机制(3)

    我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码.那从本节开始,我们开始往真实代码上面去靠拢. 事件最容易理解的例子是鼠标事件:我们 ...

  4. java class教程_深入理解Java Class文件格式(七)

    本专栏列前面的一系列博客, 对Class文件中的一部分数据项进行了介绍. 本文将会继续介绍class文件中未讲解的信息. 先回顾一下上面一篇文章. 在上一篇博客中, 我们介绍了: this_class ...

  5. java对象实例_深入理解Java对象实例生成的例子!(转)

    深入理解Java对象实例生成的例子!(转)[@more@]代码如下: class A { public int Avar; public A() { System.out.println(" ...

  6. 如何理解Java自动装箱_如何理解Java中的自动拆箱和自动装箱?

    如何理解Java中的自动拆箱和自动装箱? 自动拆箱?自动装箱?什么鬼,听都没听过啊,这...这..知识盲区... 回到家后小伟赶紧查资料,我透,这不就是问基本类型跟封装类型吗,面试官整啥名词呢... ...

  7. java画板抽象类_深入理解Java抽象类与接口

    基于抽象类与接口有太多相似之处且均体现着oop的抽象性,本文从以下几点谈谈对这两者的理解. 1.抽象类 2.接口 3.各自优缺点以及应用举例. 1.抽象类 在了解抽象类之前,先来了解一下抽象方法.抽象 ...

  8. java 线程 原子性_深入理解Java多线程与并发框架——Java内存模型与原子性、可见性、有序性...

    欢迎关注专栏<Java架构筑基>--专注于Java技术的研究与分享!Java架构筑基​zhuanlan.zhihu.comJava架构筑基--专注于Java技术的研究与分享! 后续文章将首 ...

  9. java读书心得_深入理解Java虚拟机阅读心得(三)

    Java中提倡的自动内存管理最终可以归结为自动化的解决两个问题: 给对象分配内存 回收分配给对象的内存 先说说回收这一方面的两个主要知识点 一.垃圾收集算法 1.标记-清理算法 首先标记出所有需要回收 ...

最新文章

  1. OSSEC配置文件ossec.conf中添加mysql服务
  2. docker-compose.yml 配置文件编写
  3. Hadoop开发 Hadoop视频教程 段海涛老师Hadoop完全攻克Hadoop视频教程 Hadoop开发
  4. sqlserver 事务日志已满和'PRIMARY'
  5. 解决WDCP3环境gbk网站编码程序乱码问题
  6. 职场沟通能力,不是人人都有
  7. linux 下.bashrc和.profile的区别
  8. linux clone函数ptid,pthread_create到ret_fast_syscalls 参数和栈的变化
  9. apa引用要在文中吗_【019】写作格式 | APA 7th style 引用格式
  10. 该模型是内置式的MTPA控制,速度环的输出为给定转矩,然后方式1通过求解MTPA方程得到dq给定电流
  11. 摩拜6亿美元融资之后:终极目标是打造全球移动物联网
  12. 腾讯AlloyTeam招募Web工程师(社招/校招/实习生)
  13. 【安卓开发 身份录入系统 APP】
  14. android拉起软键盘,移动端JavaScript拉起软键盘
  15. 数据分析:逻辑树分析模型
  16. Java程序员情人节_关于程序员:一封来自Java程序员的情书
  17. 关于中部城市人才外流问题的思考
  18. vue实现导出表格数据
  19. Regression 回归
  20. (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解 (转载)

热门文章

  1. mysql共享锁与排他锁
  2. HDU1850 Being a Good Boy in Spring Festival
  3. UVA 11093 Just Finish it up 环形跑道 (贪心)
  4. ostringstream使用
  5. 数据结构学习(2):汉诺塔问题
  6. UVA474 Heads / Tails Probability【数学】
  7. 51Nod-1284 2 3 5 7的倍数【数位DP+记忆化搜索】
  8. 从二项分布到泊松分布再到正态分布
  9. x=min(x, y)
  10. Tricks(七)——list of lists 行和、列和的计算