JVM原理梳理

讲JVM之前,先回顾下类加载器

类加载器一共有四类,见如下图

image
image.gif

我们都知道加载类需要类加载器,那么选用哪个类加载器呢?

JVM利用双亲委派机制,加载类时依次向上获取父类,即向上委托父类,直到Bootstarp ClassLoader,如果父类加载器为null,则判断当前类加载器是否为null,不是null则为真正的类加载器。可以理解为就远原则,但要注意自身是否为null。

如何自主加载类

有两种方式:1.Class.forName("packageName+className");

2.ClassLoader.loadClass("packageName+className");

区别:第一汇总方式不仅将类加载到jvm,还会初始化静态变量

接着说到类的生命周期

在加载类之前,类文件被编译成字节码(.class文件),由jvm解释执行程序。所以jvm加载类,实际上是加载字节码的过程。

从jvm加载类到初始化类大致分为3步

加载类-->连接-->初始化

其中连接阶段,又分为验证、准备和解析,主要为变量或对象分配内存空间和初始化

验证:hotspot(sun公司jvm的版本)验证类是否会对自身造成危害,如果不会,则将类加载进来,否则不加载。

准备:给static变量或常量分配内存,并赋予默认值。比如static int a = 100;

a赋值为0,

static String str = "abc";

str赋值为null

特殊情况,static final修饰的常量在准备阶段不仅进行赋值,还初始化。例如:

static final int b = 200;

此阶段b的值为200,而非0。

解析:将字节码中的符号引用转换为直接引用。

备注:

类初始化顺序,由上至下依次执行:

静态变量静态代码块(视代码顺序)(从类加载开始,初始化只执行一次)

非静态代码块

构造函数

初始化为类的属性(包括静态变量)赋值以及执行构造函数的过程(有先后顺序,视代码顺序定)。比如常见的new对象,在jvm中,类的初始化只会主动进行,真正开始执行java代码,而不会被动进行,因此能通过五中常见的主动方式判断类是否进行了初始化,被动方式是不会触发类的初始化的。

附从网络上搬运的5种主动出初始化方式

1、使用new字节码指令创建类的实例,或者使用getstatic、putstatic读取或设置一个静态字段的值(放入常量池中的常量除外),或者调用一个静态方法的时候,对应类必须进行过初始化。

2、通过java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则要首先进行初始化。

3、当初始化一个类的时候,如果发现其父类没有进行过初始化,则首先触发父类初始化。

4、当虚拟机启动时,用户需要指定一个主类(包含main()方法的类),虚拟机会首先初始化这个类。

5、使用jdk1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、RE_invokeStatic的方法句柄,并且这个方法句柄对应的类没有进行初始化,则需要先触发其初始化。

下面说下被动初始化的几种方式:

1.引用父类的静态变量字段;

2.定义数组对象;

3.引用类的常量(包括static final修饰的常量)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的...
    丑人林宗己阅读 3,641评论 0 2
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 7,038评论 0 4
  • 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,确实编译语言发展的一大步。 虚拟机把描述类的数据从...
    胡二囧阅读 4,533评论 0 0
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 7,575评论 0 11
  • 在一个契约体系中,契约就意味着合作,合作的目的就是让你获得别人的价值或者让别人获得你的价值,并且在这个价值交换中形...
    gyl58365阅读 3,060评论 0 0