Java 类的静态变量存放在哪块内存中?
JVM 控制的内存区域
主要分为 3 块:
线程私有区域(程序计数器、虚拟机栈、本地方法栈)
线程共享区域(堆、方法区)
直接内存(不是 JVM 运行时数据区域的一部分。如 JDK 中的 nio 使用本地函数库分配堆外内存,使用缓冲区进行这块内存的读写)
3 块内存区域的生命周期:
线程私有区域,随着用户线程的启动而创建,线程的结束而销毁。
线程共享区域,随着虚拟机的启动而创建,虚拟机的停止而销毁。
直接内存,通过本地函数库 Unsafe 分配与释放内存。
线程私有区域
1、程序计数器(Program Counter Register)
一块较小的内存空间, 是当前线程所执行的字节码的行号指示器
每条线程都要有一个独立的程序计数器
执行 Java 方法时,程序计数器记录的是字节码指令的地址;执行本地方法时,为空
唯一一个没有内存溢出区域
2、虚拟机栈(VM Stack)
描述 java 方法执行的内存模型
每个方法在执行的同时都会创建一个栈帧(Stack Frame) 用于存储局部变量表、操作数栈、动态链接、方法出口等信息
每一个方法从调用直至执行完成的过程,对应着一个栈帧在虚拟机栈中入栈到出栈的过程
栈帧是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁。方法正常完成、抛出异常未捕获都算作方法结束。
3、本地方法栈(Native Method Stack)
虚拟机栈为执行 Java 方法服务;本地方法栈为 Native 方法服务
本地方法栈深度溢出或者栈扩展失败时,也会分别抛出 StackOverflowError 和 OutOfMemoryError异常
线程共享区域
1、堆(Heap)
垃圾收集最重要的内存区域
虚拟机规范规定,创建的对象和数组都应当保存在堆内存中
一般大小可扩展,通过 -Xms 和 -Xmx 设定最小值和最大值,无法扩展时抛出 OutOfMemoryError 异常
2、方法区(Method Area)
存储被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
运行时常量池(Runtime Constant Pool)是方法区的一部分,编译期生成的各种字面量与符号引用也在其中
至此可以回答类的静态变量存放在 JVM 运行时的哪块内存了。
HotSpot VM,JDK 6 及之前版本静态变量存放在永久代(Permanent Generation,使用永久代实现的方法区)中;JDK 7 开始,静态变量改存放到 java.lang.Class 对象的末尾,即 Heap 中。虚拟机规范中,是把方法区描述为堆的一个逻辑部分,以上的差异只是实现细节的不同。
更多相关文章
- 多线程基础必要知识点!看了学习多线程事半功倍
- 模板方法模式在开源代码中应用
- 多线程三分钟就可以入个门了!
- 构造方法的参数太多,如何解决?
- 记一次应用线程被阻塞的问题排查
- 异步获取线程计算的结果-Future
- Redis为什么又引入了多线程?作者也逃不过“真香定理”?
- 详解第三种创建线程的方式-Callable接口
- java线程相关面试题(第一版)