文章目录
- 1. 程序计数器
- 2. 虚拟机栈
- 3. 栈内存溢出
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. 虚拟机栈
Java Virtual Machine Stacks (Java 虚拟机栈)
- 每个线程运行时所需要的内存,称为虚拟机栈
- 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
- 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
垃圾回收是否涉及栈内存?
不会,栈内存是方法调用的时候产生,方法调用结束的时候弹出栈。
栈内存分配越大越好吗?
物理内存是一定的,栈内存分配越大,可以支持更多方法递归调用,但是可执行的线程数就会减少。
方法内的局部变量是否线程安全?
- 如果方法内局部变量没有逃离方法的作用访问,它是线程安全的
- 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全
3. 栈内存溢出
栈帧过大、过多、或者第三方类库操作,都有可能造成栈内存溢出 java.lang.stackOverflowError ,我们可以使用使用 -Xss256k 指定栈内存大小