JVM学习—JVM内存结构与虚拟机栈

起始

学会看官网 JDK1.8参数

简介

    java文件被编译为class文件,运行时,class文件被classLoader读取,大多数时候会被解释器解释为机器码,然后被操作系统执行,但是也会被JNI通过即时编译编译为机器码,最后被操作系统执行

大多数
JAVA源文件
class文件
classLoader
字节码解释器
JNI即时编译
机器码
操作系统

内存结构

内存结构
运行时数据区
堆外内存
线程私有
线程共享
虚拟机栈 -Xss
本地方法栈
程序计数器
堆 -Xmx -Xmx
方法区

JVM运行时数据区:
图源:king老师
图源:King老师

虚拟机栈

图源:King老师
图源:King老师

方法调用时创建栈帧,并压入虚拟机栈中,当方法执行完毕时,栈帧从虚拟机栈中出栈。主要是做方法的出栈与入栈,同时,虚拟机栈是有大小限制的,可以通过-Xss来设置虚拟机栈的大小。在64位机器上,这个参数的默认值是1m,官方解释说明如下:
xss

  • 栈溢出:一般是方法调用过深,常见于递归调用
  • 内存溢出:当线程创建过多时,每个线程会占用-Xss大小的内存,最后如果内存不足,也会OOM

理解:虚拟机栈中存放是栈针,方法被调用时,创建栈针并压入虚拟机栈中,栈帧分为四个组层部分,分别是局部变量表、操作数栈、动态连接和完成出口

栈帧
局部变量表
操作数栈
动态连接
完成出口
  • 局部变量表
    局部变量表中存储当前执行的方法中创建的8大基本数据类型,对自身的引用以及对堆中对象的引用
  • 操作数栈
    如果JVM的执行引擎相当于计算器的CPU的话,那么操作数栈相当于CPU的寄存器,操作数栈中存放了当前正在执行的指令以及结果(比如加法运算会先出栈再入栈)操作数栈中的命令会被JVM执行引擎执行

引申
如果读懂了字节码,就理解了一些优化的原则,比如

int i=0;
int y=10;
int z=(i+y)*100;
return z;

int i=0;
int y=10;
return (i+y)*100;

在效率上是不同的,因为int z=的时候,需要在操作数栈中先istore再iload最后再return,但是后面的方式节省了这两个指令

程序计数器是用来做什么的

因为CPU是采用时间划片的方式轮询各个任务的,在程序计数器中记录了当前CPU在当前线程当前方法中执行的字节码的地址

为什么会有native方法?

借鉴了C C++的一些类库,而且Java在初期也没有那么多的类库

为什么会有本地方法栈

虚拟机规范,但是HotSpot将本地方法栈和虚拟机栈合并了

总结

  1. 线程私有的区域有三个:本地方法栈、虚拟机栈、程序计数器,其中,程序计数器永远不会OOM,因为程序计数器只是保存了当前CPU执行到的方法的指令的地址。
  2. 虚拟机栈中存的是栈帧,每次方法调用都会产生栈帧并压入栈中。栈帧由四部分组成:动态连接,完成出口,操作数栈,局部变量表
    2.1 局部变量表:在局部变量表中,记录了当前方法中创建的8大基本类型的变量以及对象的引用
    2.2 操作数栈:操作数栈中存储的是当前CPU要执行的指令,相当于PC的寄存器
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值