jvm学习——虚拟机基本知识

jvm学习——虚拟机基本知识

Scroll Down

jvm学习——虚拟机基本知识

总所周知,java引以为豪的是他的虚拟机计数技术,它可以屏蔽程序员对内存的直接操作,让我们的代码跨平台运行等

1.jvm的概念

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

个人理解:虚拟机是我们与硬件打交道的平台,java通过虚拟机技术减少了学习成本,字节码文件运行的地方。

2.字节码的加载流程

image.png
总体来说类加载的过程如下

加载:将.class文件加载到方法区(方法区存了类的信息)。
验证:校验字节码文件的合法性
准备:为类变量分配内存,将其赋值默认值(方法区运行的)
解析:将符号引用替换为直接引用,包含了类或接口的解析、类方法解析、接口方法的解析、字段解析,保证相互引用的完整性,激活整个类
初始化

1.类加载器(classloader,加载类的工具)

image.png
作用:完成上述的类加载的过程
种类:

1.bootstrap classloader
作用加载核心类库,随着jvm启动
2.extention classloader
扩展类加载器,加载lib目录下的jar和.class文件
3.app classloader
加载classpath下面所有的jar和.class文件,我们的代码会首先使用它加载
4.custom classloader
自定义加载器

2.双亲委派机制(类的加载规则)

除了顶层的启动类加载器以外,其余的类加载器,在加载之前,都会委派给他的父加载器进行加载,层层传递,如果父级都不能加载,才到自己加载。

双亲委派的作用:

给java的类形成了优先级层级关系,比如object类即使你覆盖了他,但是他还是会又上级系统默认的加载器加载。

3.自定义java类加载机制的例子

1.tomcat

image.png
总说周知tomcat以war应用进行发布,在同一个tomcat可以放多个不同的应用,对于一些需要加载的非基础类,会由webappclassloader优先加载,这样可以隔绝不同应用的class文件,即使他们可能依赖同一个三方jar,但是他们互相没有影响。而tomcat打破双亲委派机制,是webappclassloader会加载自己目录下的class文件,并不会传递到父加载器,但是他可以使用shareclassloader所加载的类,实现了共享与分离。

2.SPI

SPI是java提供给三方实现的API,比如我们使用的数据库驱动,由java提供规范,不同厂商实现,而他打破双亲委派机制的地方是,我们只需要在META-INF/services目录下定义接口全限定名文件,而spi就会帮我们进行动态装载。
image.png

3.内存的逻辑划分

我们现在经常的划分jvm是逻辑上的,方便我们对jvm的运行划分。

1.堆

对象生命周期发生的地方
1.8后
image.png

1.7
image.png

2.虚拟机栈

栈是一种数据结构,运行顺序为压栈弹栈。
jvm的虚拟机栈是基于线程,在线程的生命周期中,参与计算的数据会频繁的入栈和出栈,栈的生命周期与线程一样。个人理解我们每个方法调用都会进入栈,创建一个栈帧,而完成就会出栈。
栈帧的四个区域:

局部变量表::存放输入参数和输出参数以及方法内的局部变量(局部变量
表在编译期间完成分配,当进入一个方法时,这个方法在帧中分配
多少内存是固定的)
操作数栈:方法执行对应的操作数,:记录出栈、入栈的操作。
动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。运行期间将方法区的符号应用变为直接应用。
方法出口:当一个方法开始执行后,只有两种方式可以退出,一种是遇到方法返回的字节码指令;一种是遇见异常,并且这个异常没有在方法体内得到处理。

3.程序计数器

程序计数器是一块较小的内存空间,是当前线程所执行的字
节码的行号指示器

• 程序计算器处于线程独占区
• 如果线程执行的是java方法,记录的是正在执行的虚拟机字节
码指令的地址,如果是native方法,这个计数器值为undefined

4.方法区

线程共享的区域,存放类信息(类的版本、字段、方法、接口),静态变量、常量、方法数据、方法代码,运行时常量池(存放编译期生成的各种字面量和符号
引用,这部分内容将在类加载后存放到常量池中)。
Jdk1.6及之前: 有永久代, 常量池1.6在方法区
Jdk1.7: 有永久代,但已经逐步去永久代,常量池1.7在堆
Jdk1.8及之后: 无永久代,常量池1.8在元空间

5.本地方法栈

作用是支撑native方法的调用