JVM04_虚拟机栈概述、局部变量表、操作数栈、动态链接、方法的返回地址、附加信息(一)

简介: ①. 什么是Java virtual machine?②. 局部变量表(LocalVariables)

前言:


(栈并不是越大越好,越多可以防止出现StackOverflowError晚点出现,但是栈越大,也就代表着虚拟机栈是一定的,你的栈越大,别的栈就会小)


①. 什么是Java virtual machine?


  • ①. 栈的概述
    每创建一个线程就会创建一个Java栈,每一个Java栈中都会有很多栈帧(局部变量表 | 操作数栈 | 动态链接 | 方法返回地址 | 一些附加信息)


注意:虚拟机栈中不存在GC,但是存在StackOverflowError和OOM


解释:


(1). 虚拟机栈(Java Virtual Machine Stacks)和线程是紧密联系的,每创建一个线程时就会对应创建一个Java栈,所以Java栈也是"线程私有"的内存区域,这个栈中又会对应包含多个栈帧,每调用一个方法时就会往栈中创建并压入一个栈帧,栈帧是用来存储方法数据和部分过程结果的数据结构,每一个方法从调用到最终返回结果的过程,就对应一个栈帧从入栈到出栈的过程[先进后出]


(2). 栈帧中有如下部分组成:


微信图片_20220106133447.png(3). 栈的其他介绍


微信图片_20220106133518.png


  • ②. 存放于栈中的东西如下
    (8种基本类型的变量+对象的引用变量+实例方法都是在函数的栈内存中分配[局部变量])


  • ③. 栈内存溢出(StackOverflowError) -Xss参数


  1. 栈帧过多导致栈内存溢出(方法的递归调用,没设置正确停止条件)


  1. 局部数组过大。当函数内部的数组过大时,有可能导致堆栈溢出


      Exception in thread "main" java.lang.StackOverflowError
    //sayHello()发生了递归
    public class DemoT {
        public static void main(String[] args) {
            sayHello();
        }
        public static void sayHello(){
            sayHello();
        }
    }


④. Java虚拟机规范允许Java栈的大小是动态的或者是固定不变的 掌握


如果采用固定大小的Java虚拟机栈,那每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。


如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出一个StackoverflowError异常


如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者是在创建新的线程时就没有足够的内存区创建对应的虚拟机栈,那Java虚拟机将会抛出一个OutOfMemoryError异常


⑤. 如何设置栈内存的大小? -Xss size (即:-XX:ThreadStackSize)


一般默认为512k-1024k,取决于操作系统(jdk5之前,默认栈大小是256k;jdk5之后,默认栈大小是1024k)


栈的大小直接决定了函数调用的最大可达深度


平台 jdk8
linux 1024
MacOS 1024
window 0


⑥. 栈和堆的区别是什么?


从GC、OOM、StackOverflowError的角度。


(栈中不存在GC,当固定大小的栈会发生StackOverflowError,动态的会发生OOM。堆中GC、OOM、StackOverflowError都存在)


从堆栈的执行效率


(栈的效率高于堆)


内存大小,数据结构


(堆的空间比栈的大一般,栈是一种FIFO先进后出的模型。堆中结构复杂,可以有链表、数组等)


栈管运行,堆管存储


②. 局部变量表(LocalVariables)


①. 定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量(这些数据类型包括各种基本数据类型、对象引用(reference)以及return Address类型)


②. 由于局部变量是建立在线程的栈上,是线程私有数据,因此不存在数据安全问题


③. 局部变量表所需容量大小是在编译期确定下来的。(并保存在方法Code属性的maximum local variables数据项中,在方法运行期间不会改变局部变量表的大小的)


//使用javap -v 类.class 或者使用jclasslib
public class LocalVariableTest {
    public static void main(String[] args) {
        LocalVariableTest test=new LocalVariableTest();
        int num=10;
        test.test1();
    }
    public static void test1(){
        Date date=new Date();
        String name="xiaozhi";
    }
}


jclasslib说明:


微信图片_20220106133738.png微信图片_20220106133742.png


image.png


④. 关于slot的理解(引用数据类型(方法的返回地址)占用1个slot)


局部变量表,是基本的存储单元是slot(变量槽)


在局部变量表中,32位以内的类型只占有一个slot(包括引用数据类型),64位的类型(long和double)占有两个slot


byte、short、char在存储前被转换为int,boolean也被转换为int(0表示fasle,非0表示true)。long和double则占据两个slot


  • ⑤. Jvm会为局部变量表中的每一个slot都分配一个访问索引,通过这个索引即可成功访问到局部变量表中指定的局部变量值


  • ⑥. 如果需要访问局部变量表中一个64bit的局部变量值时,只需要使用前一个索引即可(比如:访问long或double类型变量)


微信图片_20220106133842.png


⑦. 如果当前帧是由构造方法或者实例方法创建,那么该对象引用this将会放在index为0的slot处


微信图片_20220106133900.png


⑧. 栈帧中的局部变量表中的槽位是可以复用的,如果一个局部变量过了其作用域,那么在其作用域之后申请的新的局部变量就很可能会复用过期局部变量的槽位,从而节省资源的目的


  public void localVar2(){
    {
      int a=0;
      System.out.println(a);
    }
    //此时的b就会复用a的槽位
    int b=0;
  }


⑨. 与GC Roots的关系


局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都不会被回收


相关文章
|
3月前
|
Java
程序计数器和虚拟机栈
这篇文章介绍了Java虚拟机(JVM)的内存结构,特别解释了程序计数器(Program Counter Register)的作用,即用来记录下一条JVM指令的执行地址和行号。
程序计数器和虚拟机栈
|
3月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
3月前
|
缓存 监控 算法
吃透 JVM 诊断方法与工具使用
【8月更文挑战第4天】深入了解并掌握JVM诊断需把握几大要点:1) 熟悉JVM内存模型,如堆、栈及方法区;2) 掌握垃圾回收机制与算法;3) 运用工具如`jps`(查看Java进程)、`jstat`(监控运行状态)、`jmap`(生成堆快照)、`jhat`(分析堆快照)、`jstack`(检查线程栈); 4) 利用专业工具如Eclipse Memory Analyzer分析堆转储文件查找内存泄漏; 5) 动态监控与调整JVM参数; 6) 结合日志分析性能瓶颈。通过实战案例加深理解,有效应对JVM性能问题。
|
4月前
|
监控 安全 Java
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
114 2
|
4月前
|
开发者 Java
JVM内存问题之top命令的物理内存信息中,'used'和'free','avail Mem'分别表示什么
JVM内存问题之top命令的物理内存信息中,'used'和'free','avail Mem'分别表示什么
|
4月前
|
云计算
云计算问题之线程请求的栈深度大于虚拟机所允许的深度如何解决
云计算问题之线程请求的栈深度大于虚拟机所允许的深度如何解决
30 1
|
3月前
|
安全 Java
虚拟机栈的五道面试题
这篇文章提供了关于Java虚拟机栈的五个面试问题,涉及栈溢出的情况、栈大小调整、栈内存的分配、垃圾回收与虚拟机栈的关系以及局部变量的线程安全性。
|
4月前
|
缓存 Prometheus 监控
Java面试题:如何监控和优化JVM的内存使用?详细讲解内存调优的几种方法
Java面试题:如何监控和优化JVM的内存使用?详细讲解内存调优的几种方法
92 3
|
4月前
|
缓存 监控 算法
Java面试题:讨论JVM性能调优的常见方法和技巧。
Java面试题:讨论JVM性能调优的常见方法和技巧。
54 1
|
3月前
|
监控 Java Android开发
吃透 JVM 诊断方法与工具使用
【8月更文挑战第3天】要精通JVM诊断,需掌握关键监控指标如内存(堆/非堆)、CPU使用及线程状态;熟悉工具如`jstat`(监控状态)、`jmap`(堆转储)、`jstack`(线程堆栈);并能利用Eclipse Memory Analyzer (MAT)分析堆转储找内存泄漏;同时理解GC日志以优化垃圾回收行为;通过实践案例加深理解。