深入理解JVM

本文详细介绍了Java虚拟机(JVM)的内存结构,包括线程公有的堆和方法区,以及线程私有的虚拟机栈、本地方法栈和程序计数器。堆内存主要存储对象实例,分为新生代和老年代。方法区存储类信息和常量。虚拟机栈负责方法执行,每个栈帧包含局部变量表、操作数栈、动态链接和返回地址。本地方法栈服务于本地方法。程序计数器记录当前线程执行的指令。此外,文章还提及了垃圾收集算法和JVM参数,以及类加载机制。
摘要由CSDN通过智能技术生成

什么叫JVM虚拟机?

java虚拟机(java virtual machine,JVM),一种能够运行java字节码的虚拟机。作为一种编程语言的虚拟机,实际上
不只是专用于Java语言,只要生成的编译文件匹配JVM对加载编译文件格式要求,任何语言都可以由JVM编译运行。
比如kotlin、scala等。

JVM虚拟机分为哪几部分?

在这里插入图片描述
虚拟机主要分为线程公有和线程私有两部分,堆和方法区是属于线程私有的,虚拟机栈、本地方法栈、程序计数器是属于线程共有的。
分别说下他们的作用

线程公有

堆主要是用来存放创建的对象实例的,Java 堆分为新生代和老年代。新生代分为 eden 区、s0 区、s1 区,s0 区和 s1 区是两块大小相等、可以互换角色的内存空间
几乎所有的对象都存放在堆中。Java 堆是自动化管理的,垃圾对象会被自动清理,不需要程序员手动释放内存。
新生代存放新生的和年龄不大的对象。对象首先分配在 eden 区,如果在一次新生代回收后还存活就会进入 s0 或 s1,对象年龄增加 1。当对象达到一定年龄后,就会进入老年代,老年代存放老年对象。(堆内存作为最主要的内存空间,会在之后的垃圾回收中详细讲解)

方法区

方法区和java堆一样是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息(class 文件)、常量(final)、静态变量、及时编译器(JIT)编译后的代码等数据
方法区:存放两部分内容。
① 类加载子系统加载的类信息;
②Java 程序运行时的常量池信息,包括字符串字面量和数字常量。
方法区是线程共享的。
JDK6、JDK7 永久代实现方法区,JDK8 之后永久带被彻底移除,被元数据区取代。元数据区数堆外的直接内存

线程私有

虚拟机栈

java虚拟机栈和程序计数器一样也是线程私有的,它的生命周期和线程相同,虚拟机栈描述的是java方法执行的内存模型,每个方法在执行的同时都会创建一个帧栈用于存储局部变量表、操作数栈、动态连接、返回地址等信息
在这里插入图片描述
局部变量表
局部变量表存放了编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double)、对象引用(reference类型,它不等同于对象本身,可能指向一个代表对象的句柄或者其他与此对象相关的变量)和retureAddress类型。其中64位长度的long和double类型的数据会占2个局部变量空间,其余的类型只占1个
局部变量表所需的内存空间是在编译期分配完成的,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期不会改变局部变量表的大小。

操作栈
操作数栈也称为操作栈,是一个先入后出的数据结构结构,同局部变量表一样操作数栈的深度也是在编译阶段确定的。操作数栈的每一个元素可以是任意的java类型,包括long和duble。32位数据类型所占的栈容量位1(4个字节),64位数据类型占用的栈容量为2(8个字节)。
栈帧刚创建的时候,操作数栈 是空的。方法执行的过程中,会有各种字节码指向操作数栈中写入和提取,也就是入栈与出栈操作,
列如,在做算术运算的时候是通过操作数栈来进行的,又或者在调用其他方法的时候是通过操作数栈来进行参数传递的。
另外在虚拟机概念模型中,两个栈帧作为虚拟机栈的元素,相互之间完全是独立的。但大多数虚拟机的实现都会做一些优化处理, 令两个栈帧出现一部分重叠。让下面栈帧部分的操作数栈和上面栈帧部分的局部变量表重叠在一起,这样在进行方法调用的时候就可以共用一些数据了,无需额外的参数复制传递过程,重叠过程如下图所示:

动态链接
一个方法调用另外的方法,或者一个类使用另外一个类的成员变量时,都需要通过直接引用来调用。代码经过编译后,会形成字节码文件,字节码文件中存储的都是符号引用,执行引擎需要使用直接引用,符号引用需要转换为直接引用,一部分符号引用会在类加载或者第一次使用时进行解析,称为静态解析;另外一部分符号引用需要在代码执行时动态进行解析,称为动态链接。

返回地址
当一个方法执行结束后,有两种方式可以退出这个方法,第一种是遇到方法的返回指令,这时候会有返回值传递给方法的调用者,这种返回方式称为正常返回;第二种返回方式是异常返回,方法执行过程中遇到内部异常,或者在异常表中没有搜索到匹配的异常处理器,会导致方法退出,这种方式不会给方法调用者返回值。
无论何种方法退出,都需要返回到方法调用者的位置,程序才能继续执行,正常退出时,栈帧中会存放方法调用者的PC计数器的值,用以回复调用者的执行状态;异常退出时,需要通过异常处理表来确定,这时候栈帧中不存放异常信息。

本地方法栈

本地方法栈和虚拟机栈的作用十分相似,虚拟机栈为虚拟机执行java方法(也就是字节码服务)而本地方法栈则为虚拟机使用的Native方法服务。

程序计数器

Java 虚拟机会为每个 Java 线程创建 PC 寄存器,所以 PC 寄存器也是每个线程的私有空间。Java 线程正在执行的方法称为当前方法,如果当前方法是 Java 方法,PC 寄存器就会执行当前正在被执行的指令;如果当前方法是本地方法,PC 寄存器的值就是 undefined

垃圾收集算法

JVM参数

类加载机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值