这篇文章就以实战的方式看看「静态变量」「实例变量」「局部变量」存放的位置!
首先要搞清楚一个概念,「静态变量」「实例变量」「局部变量」指的是引用本身,而非它们所指向的对象,它们所指向的对象毫无疑问肯定都存放在堆上,关于这个观点更多分析可见 逃逸分析
还需要强调一个点,这里是基于 JDK8 的 HotSpot 虚拟机!!
根据理论知识可以知道:「静态变量」在 JDK7 及以后就存放在 Java 堆中;「实例变量」随着对象实例存放在 Java 堆中;「局部变量」存放在方法栈帧的局部变量表中
首先给出一段测试代码:
public class Test {
static class Person {
// 静态变量
static ObjectHolder staticObj = new ObjectHolder();
// 实例变量
ObjectHolder instanceObj = new ObjectHolder();
void foo() throws InterruptedException {
// 局部变量
ObjectHolder localObj = new ObjectHolder();
// 休眠,不然方法执行完,方法栈帧就会出栈
Thread.sleep(10000000);
}
}
private static class ObjectHolder {}
public static void main(String[] args) throws InterruptedException {
Person person = new Person();
person.foo();
}
}
我们先分析一下,按照理论来说,此时 Java 堆中肯定存在 3 个ObjectHolder
对象实例,同时staticObj
和instanceObj
也都在 Java 堆中
下面通过 VisualVM + JProfiler 软件测试一下!!首先用 VisualVM 保存一个 Java 堆的 dump文件,如下所示:
用 JProfiler 打开这个 dump 文件,可以发现在 Java 堆中刚好有 3 个ObjectHolder
对象实例,如下图所示:
我们再找找「静态变量」在哪里,在java.lang.Class
中可以发现我们定义的静态变量staticObj
,而这个静态变量指向的对象实例是0xa87
,如下图所示:
继续找「实例变量」在哪里,在com.lfool.myself.Test$Person
中可以发现我们定义的实例变量instanceObj
,而这个实例变量指向的对象实例是0xc3b
,如下图所示:
到此为止,我们找出来的所有内容都存放在 Java 堆中,至于「局部变量」,可以通过 JHSDB 软件在栈中发现,这里就不演示了!!!