【JVM】浅析程序计数器与虚拟机栈

迈不过友情╰ 2024-03-30 10:14 117阅读 0赞

文章目录

    1. 程序计数器
    1. 虚拟机栈
    1. 栈内存溢出

1. 程序计数器

Program Counter Register 程序计数器(寄存器)

程序计数器的作用是什么?

是记录下一条JVM指令的执行地址行号

程序计数器有什么特点?

  • 线程私有的
  • 不会存在内存溢出

    0: getstatic #20 // PrintStream out = System.out;
    3: astore_1 // —
    4: aload_1 // out.println(1);
    5: iconst_1 // —
    6: invokevirtual #26 // —
    9: aload_1 // out.println(2);
    10: iconst_2 // —
    11: invokevirtual #26 // —
    14: aload_1 // out.println(3);
    15: iconst_3 // —
    16: invokevirtual #26 // —
    19: aload_1 // out.println(4);
    20: iconst_4 // —
    21: invokevirtual #26 // —
    24: aload_1 // out.println(5);
    25: iconst_5 // —
    26: invokevirtual #26 // —
    29: return

  • 解析器将指令解析为机器码将给CPU执行,程序计数器会记录下一条指令的地址行号,这样下一次解析就能从计数器拿到指令然后进行解析执行。

  • 而在多线程情况下,如果两个线程发生了上下文切换,那么程序计数器会记录线程下一行指令的地址行号,以便于接着往下执行。

2. 虚拟机栈

image-20221218123059498

Java Virtual Machine Stacks (Java 虚拟机栈)

  • 每个线程运行时所需要的内存,称为虚拟机栈
  • 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

垃圾回收是否涉及栈内存?

不会,栈内存是方法调用的时候产生,方法调用结束的时候弹出栈。

栈内存分配越大越好吗?

物理内存是一定的,栈内存分配越大,可以支持更多方法递归调用,但是可执行的线程数就会减少。

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

  • 如果方法内局部变量没有逃离方法的作用访问,它是线程安全的
  • 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全

3. 栈内存溢出

栈帧过大、过多、或者第三方类库操作,都有可能造成栈内存溢出 java.lang.stackOverflowError ,我们可以使用使用 -Xss256k 指定栈内存大小


发表评论

表情:
评论列表 (有 0 条评论,117人围观)

还没有评论,来说两句吧...

相关阅读

    相关 jvm 虚拟

    JVM虚拟机栈是每个线程都拥有的内存区域,用于执行方法调用。在源码层面,虚拟机栈由复杂的C++实现控制,与Java开发者的日常工作关联不大。但是,理解虚拟机栈如何工作有助...