JVM学习笔记(一)——内存模型,类加载过程

JVM整体架构

JVM整体架构.png

字节码文件编译到Class loader system。
其中方法区和堆(黄颜色)是线程共享的,其他三个是每个线程独有一份的。

Java代码执行过程

因为操作系统不识别高级语言,只识别机器指令,所以需要从高级语言=》汇编语言=》机器指令。
Java文件从编译器到字节码文件,字节码文件从类加载器到校验器最后到编译执行。
JIT编译器可以将多次执行的热点代码缓存起来,下次可以直接使用,提高了效率。

Java文件到编译到操作系统的一个过程

JVM的生命周期

image.png
image.png

JVM发展历程

Sun Classic VM:世界上第一款商用Java虚拟机。
这款虚拟机内部只提供解释器。

Exact VM

Hot Spot:现在的jdk都是基于该虚拟机。
BEA的JRockit:这款虚拟机内部没有解释器,就通过即时编译器。是世界上最快的JVM。
IBM的J9
Apache的Harmony

解释器和JIT即时编译器.png
解释器和JIT即时编译器,可以不是同时存在的。
早期的java虚拟机就只有解释器,但是这样就会导致效率很低下,比如循环里一段重复的代码要重复,所以加上JIT即时编译器,就会将一些热点代码缓存起来,配合使用,效率更快。

类加载器子系统

class load system:加载字节码文件,分为三大步骤。
1、加载阶段。
2、链接阶段。
3、初始化阶段。

类加载器子系统.png

类的加载过程

类的加载过程.png

1、加载

加载.png

2、链接

链接.png

变量的加载过程.png

变量在prepare只是生成默认的初始值,在后面的inital初始化才会给它赋值。
常量,final修饰的,在prepare就会进行初始化。

3、初始化

image.png

image.png

() 对应字节码.png

< clinit >() 就是类里静态赋值的过程。如上图。
上述先linking中的prepare将各个变量做初始化操作。
再由< clinit >() 方法自上而下做赋值操作。
变量num: 先给1,在给2.
变量number: 先给20,在给10.
所以,当定义在static下面时,此时打印出的是下面的值。

< init >() 是指构造函数里的赋值过程。
java每个类都必须有构造函数,所以肯定也会有< init >() 方法。
但,如果没有给static之类的类变量,则可以没有< clinit >() 。

如果存在继承关系
继承关系初始化.png

如上图所示。main用到了son这个类,所以去引用它,引用之前发现son用到father,所以要先初始化father(加载,链接,初始化)一系列操作后,A=2,所以son去引用时,就是2这个值。可以看下面的字节码源码。

继承字节码加载源码

一个类的< clinit >() 方法在多线程下会在被同步加锁
() 方法在多线程下会在被同步加锁.png
上述可以看出,两个类在runnable里都要初始化这个类,一个线程进来后锁住了,另一个进不来,导致阻塞。

类加载器分类

引导类加载器:是由C/C++编写的,在java里获取不到,为null,主要加载java的核心类库。
扩展类加载器,系统类加载器:都是由java写的。可以通过getParent()获取。我们自己写的java类也是由该加载器进行加载。

启动类加载器和扩展类加载器加载的jar.png

双亲委派机制

如果你创建一个包名叫java.lang的包,下面创建一个叫做String的类。这时候,你新建一个测试类去new这个String,会出现什么问题呢?会加载吗?

其实这时候会将委托抛给上层的父类,逐级往上,到引导类的时候,引导类刚好是加载核心java类下的(lang包归他管)所以他就加载系统String了。
如果父类没完成加载任务,子加载器才会自己去尝试加载。

双亲委派

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值