JVM原理梳理

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

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

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

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修饰的常量)

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值