JDK1.8中的基本类型静态变量的存储位置
欢迎来到我的博客:TWind的博客
我的CSDN::Thanwind-CSDN博客
我的掘金:Thanwinde 的个人主页
前言
之前写JVM内存结构时,在一个问题上卡了很久
众所周知,JDK1.7时,方法区只存储基本类型的静态变量,引用类型的已经转移到堆中了
那么,JDK1.8时,方法区还存储着基本类型的静态变量吗?毕竟方法区都已经成了永久代了
对于这个问题,可谓是众说纷纭,什么都有
但是在《深入理解Java虚拟机:JVM高级特性与最佳实践》中,明确提到了,JDK1.7就已经将静态变量移入堆中
但实际来说,这个说法并不准确...
可以知道,实际上是JDK1.8才完全移除了永久代,类元数据、内部字符串和类静态变量将从永久代移动到 Java 堆或本机内存
那么,在JDK1.8的基本类型静态变量到底是存储在本机内存还是堆中?让我们做一个实验
代码:
public class test1 {
static long a0 = 1;
/*......
......*/
static long a9999 = 1;
public static void main(String[] args) throws IOException {
for(int i = 0;i < 10000;i ++)
System.out.println("static long a" + i +" = 1;");
System.in.read();
}
}
类似于这种代码,生成10000行的 static,一个static变量有8字节,那么应该会有80KB的大小
然后我们将其跑起来,然后抓取其堆快照,分析里面是否有这80KB的数据,这就是我们的大致思路
但实际上,这种思路并不是很好:
尽管10000个long已经有了80KB,但比起log,jit动辄几MB的内存还是太难看到,运行过程中的平均内存波动必然会远远超过80KB,所以不能通过看变化的方法来验证
解决方法还是抓堆快照,但我们只需要找到这个类的实例,看看里面有没有这10000个static的数据就行
VisualVM
VisualVM: Home自行下载,主要是拿来抓取栈帧
启动测试项目后,打开VisualVM,里面在左边应该能看到
接着转入右边的
点击HeapDump获取堆快照
在快照界面,点击[view all],然后在下方的Class Filter,搜索“test1”(你的类名)
然后你会发现
显示这个实例大小为0,但是你点击上方的
就会发现
这不就是那些变量吗?全部的都读出来了
为什么会这样?因为堆快照强行规定了实例的大小是0
但这并不影响,既然我们在堆快照中看到了这10000个变量都在,而且值都在,这就说明
基本类型静态变量和引用类型静态变量一样,是储存在堆内存之中的
也可以说,静态变量全部是存在堆中,方法区只是存了对堆中实例对象的引用