JVM结构
程序计数器(PC Register)
记录下一条jvm指令的执行地址
线程私有,各个线程独立运算不会混乱
不存在内存溢出
它是一块很小的内存空间,几乎可以忽略不记。也是运行速度最快的存储区域。
在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。
任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的java方法的JVM指令地址:或者,如果是在执行native方法,则是未指定值(undefined)
它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
字节码解释器工作时就是通过改变这个计数器的值来选取下一个条需要执行的字节码指令。
它是唯一一个在Java虚拟机规范中没有规定任何OOM情况的区域。
虚拟机栈(JVM stacks)
线程运行时需要的内存空间
- 栈由栈帧组成,每个栈帧对应每次方法调用时占用的内存(参数,局部变量,返回地址),调用方法时入栈占用内存,调用完毕弹栈释放内存,每个线程一个虚拟机栈,同一时间只能有一个活动栈帧,对应当前正在执行的方法
- 虚拟机栈不涉及GC
- 栈内存划分越大,线程数上限就少了,但是可以允许单个线程更多次的递归调用
- 栈帧中局部变量线程安全
- 栈帧中形参为基本类型线程安全
- 栈帧中形参为引用类型线程不一定安全
- 当递归次数过多后,可能出现StackOverFlowException栈内存溢出,配置MV选项-Xss2048k修改栈大小
本地方法栈(Native Method Stacks)
- 本地方法是指用底层语言(C/C++)编写的方法使用的栈
- 每个线程一个本地方法栈
堆(Heap)
- 通过new创建的对象存储在堆内存中
- 堆是线程共享的,需要考虑线程安全
- 有垃圾回收机制
- 配置MV选项-Xmx8m修改堆空间大小,改小一些可以提前预知一些堆空间不足引起的bug
- jconsole虚拟机监控软件
方法区(Method Area)
存储类的field constructer methods
1.8之前用PermGen永久代实现,1.8用Metaspace元空间实现
元空间默认用系统内存,可以自己设置上限大小-XX:MaxMetaspaceSize=8m
如果自动生成过多的类可能导致方法区内存溢出报错
- 常量池:它是一张常量表,在*.class文件中,指令通过这张常量表找到要执行的类名,方法名,参数类型,字面量等信息
- 运行时常量池:当类呗加载时,常量池信息呗放入运行时常量池中,把#符号地址变为真实地址
- 字符串池:出现字符串常量的时候,如果字符串池中没有这个字符串就懒加载到字符串池中,intern()将字符串手动加入串池并引用,返回值为串池中的字符串的引用
https://www.cnblogs.com/niugang0920/p/12424671.html