JVM篇:JVM内存结构

目录

程序计数器

虚拟机栈

栈问题

垃圾回收是否涉及栈内存

栈内存分配越大越好吗

方法的局部变量是否线程安全

本地方法栈

堆问题

堆内存溢出

堆内存诊断

方法区

常量池

运行时常量池


程序计数器

程序计数器英文名叫:Program Counter Register

作用:用来记录下一条jvm指令的地址行号。

先来查看一段jvm指令,这些指令对应的java代码就是输出1-5

操作系统运行该Java程序时具体流程如下

语言解释:源文件通过编译转化为二进制字节码文件后,解释器会获取第一行jvm指令后解释为机器码供CPU执行,与此同时程序计数器记录下一条jvm指令的行号,随后解释器从程序计数器中获取应该解释哪条jvm指令供CPU执行,由于程序计数器需要频繁的更新jvm行号,为了保证响应速度,jvm在设计时采用寄存器实现程序计数器。

特点:

  • 线程私有(即当CPU在执行线程1过程中去执行线程2,程序计数器会保留线程1的下一条指令的地址行号,等到线程1恢复执行时接着下一条指令接着执行。每个线程都有自己的程序计数器)
  • 是JVM唯一一个不会存在内存溢出问题区域。

虚拟机栈

每个线程所需要的内存空间我们使用虚拟机栈来表示(早期也叫Java栈),每个栈由栈帧组成,栈帧对应的是方法调用时所需的内存,每个线程只存在一个活动栈帧,即正在执行的方法

接下来,我们结合代码理解虚拟机栈

在上述代码中,当我们执行到method2方法时,栈帧一共存在3个分别是main方法的栈帧,method1的栈帧与method2的栈帧,并且method2的栈帧在栈的顶部

栈问题

垃圾回收是否涉及栈内存

垃圾回收器针对的是堆内存中无用的对象,而栈内存对应的是调用方法所需要的内存,而方法执行结束后会自动释放内存,因此垃圾回收并不需要管理栈内存。

栈内存分配越大越好吗

并不是。电脑的内存大小是固定的,栈内存分配越多可能会导致线程数量减少。比如一个内存为500M的电脑,栈内存分配为1M,则理论说该电脑可以存在500个线程,如果栈内存分配为2M,则理论线程就为250个。

方法的局部变量是否线程安全

对于变量是否是线程安全,主要是看该变量是共享的还是私有的。

本地方法栈

与栈内存相似,不过提供的不是线程所需内存而是给本地方法提供内存(本地方法指的是通过java调用其他语言编写的方法)

通过new创建出来的对象都存储在堆内存中

特点:堆内存中的变量是线程共享的。具有垃圾回收机制

堆问题

堆内存溢出

虽然堆存在垃圾回收机制,但是垃圾回收机制只能回收不再使用的对象,如果对象正在被使用是不会被回收的,由于堆内存默认大小为4G,当我们的程序在短时间内的执行可能不会暴露堆内存溢出的情况,这时我们可以设置堆内存小一些进行测试(命令为-Xmx[指定大小])。

堆内存诊断

  • jps 工具
    查看当前系统中有哪些 java 进程
  • jmap 工具
    查看堆内存占用情况 jmap - heap 进程id
  • jconsole 工具
    图形界面的,多功能的监测工具,可以连续监测

方法区

线程共享区域,用来存储类的结构

方法区可能会存在内存溢出的情况,在实际场景中,spring与mybatis经常会动态的加载一些类,因此当程序运行期间创建了足够多的类可能会导致方法区内存溢出(JDK1.8之前叫做永久代内存溢出,JDK1.8之后叫做源空间内存溢出)

常量池

首先查看一个示例代码,是一个最基本的入门案例

public class Demo1 {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

下面我们通过对该类的编译后的class文件进行反编译得到二进制字节码文件

javap -v Demo1.class

在二进制字节码文件中,存储了类的基本信息,常量池,类方法定义,包含了虚拟机指令

类的基本信息如下

常量池信息如下(只粘贴了一部分)

类方法定义信息如下

而虚拟机指令存储在类的方法定义中

在上面截图中,需要具体获取哪些静态变量加载哪些参数都需要从常量池中获取,而在常量池中的哪些位置需要从后面的#号中获取,就以该例子为例。首先是需要获取#2中的数据,那么我们去常量池中找该行的信息

运行时常量池

常量池是*.class文件中的,当该类被加载时,它的常量池信息就会被放入运行时常量池,并把里面的符号地址变为真实地址(简而言之就是在运行时会将常量池中的#1,#2转化为内存中的真实地址,而不是#1#2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zmbwcx2003

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值