type
status
date
slug
summary
tags
category
icon
password
什么是 JVM
JVM就是 java 虚拟机,是 java 程序的运行环境。
好处
- 一次编写,到处运行。jvm 隔离了底层环境和字节码,得以实现平台无关性
- 自动内存管理机制,垃圾回收功能。这里对标的是 C 和 C++语言,他们没有自动内存管理机制,需要程序员手动进行释放内存,而 java 提供了这种自动内存管理机制,降低了程序员的负担。
- 数组下标越界异常检查。在 C 和 C++中,是没有这种数组下标越界检查的,需要程序员自己操作。如果没有捕获,那么就有可能会超出下标占用其他程序的内存,而 jvm 提供了下标越界检查。
学习路线

本地方法接口是用来调用底层系统的。
程序计数器作用
下图程序执行的流程

右边是 java 代码,左边是对应的二进制字节码,解释器拿到 jvm 指令翻译为机器码,机器码再交给 cpu 执行。
程序计数器的作用:记录下一条jvm指令的地址,以达到 cpu 可以连续执行,程序计数器就是寄存器,因为他是读取最快的,这样程序执行的效率会高很多。

程序计数器的特点
- 线程私有:从上面的图可以看出,好像不需要程序计数器,cpu逐行执行就可以了,但这只适合单线程,在多线程的情况下,每一个线程抢到一个时间片去执行代码,由程序计数器提供下一条jvm执行的指令。
- 不会出现内存溢出的情况
栈
线程运行需要的内存空间
栈是一个后进先出的数据结构,每一个进栈的模块称之为栈帧,每一个栈帧指的是方法运行所需要的内存空间,当要执行一个方法的时候就会把栈帧入栈,执行完之后取出,释放内存,当一个方法中又去调用另一个方法,这样进行循环调用的时候,多个栈帧就会入栈,先执行最上面的一次执行。这也是为什么当程序报错的时候要去最上面的错误开始看,因为是从最上面的执行错误开始,逐渐向下面抛出。
虚拟机栈
- 每个线程运行时所需要的内存,成为虚拟机栈
- 每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存
- 每个线程只能有一个活动栈帧,也就是正在执行的方法
垃圾回收是否会涉及栈内存?
不需要,栈运行的是一个个方法,每次运行完都会自动释放,不需要垃圾回收来进行回收内存。
栈内存分配越大越好吗?
栈内存可以通过虚拟机参数进行设置,参数名为- xss,默认情况下是 1024KB,物理内存是固定的,栈内存越大,线程数就会越少,所以并不是越大越好。
方法内的局部变量是否是安全的
一个线程是一个栈,如果有两个线程都去执行一个方法,那么就会在各自的线程的栈内行成一个栈帧,对各自的栈内的局部变量进行修改,是不影响的,所以是线程安全的。
在第一个方法中 StringBuilder 在方法内,所以是线程安全的,这是一个栈帧,而第二个和第三个方法,一个是对象通过参数传递进去的,一个是通过返回值返回的,这样的话,StringBuilder 对象都有可能被其他线程去执行,所以不是线程安全的。
所以如果方法内部局部变量没有逃离方法的作用访问,那么就是线程安全的,如果局部变量引用了对象,并逃离方法的作用方法,就要考虑线程安全了。

栈内存溢出
什么情况下会导致溢出
- 递归调用,方法内部自己调用自己,即使有多大的栈都会把栈内存用完。
- 栈帧过大,一个栈帧过大导致栈全部占满,这种不太可能会出现,因为一个栈就是一个方法,方法内部是一些变量,一个 int 才 4 个字节,栈内存默认 1M,这样的话需要很多栈才会占满。
- 栈帧过多导致栈占满。
线程诊断 cpu 过高