Posts 类变量与实例变量的内存存储
Post
Cancel

类变量与实例变量的内存存储

变量有类变量、实例变量和局部变量。局部变量比较好区别。类变量与实例变量的区别就在于前者在类中被定义时有static修饰符。 类变量属于类级别,因此在多个线程中引用时是共享的,因此只存在于一个内存区域。而实例变量仅仅属于类定义的具体实例,多个实例之间不共享实例变量,因此他们使用不同的内存地址。

这里就出现了一个问题。实例都是类的具体定义,都是保存在heap堆中,因为堆都是保存具体的对象,所以实例变量也一定会保存在heap堆中。heap堆中因此一定不会存储类变量,因为类变量不属于任何对象。废话那么多,那类变量储存在哪个内存区域呢?

通过具体的例子来看看就明白了。

1
2
3
4
5
6
7
8
9
10
11
12
13
package cn.xwiz.lab.jvm.Static;

public class ClassA {
	static String[] s1 = new String[99999];
	private String[] s2 = new String[88888];
	
	public ClassA() {
		//
	}
	public void doNothing(){
		System.out.println("do nothing");
	}
}

在ClassA类中,我定义了s1的静态变量,它就是类变量;s2为非静态变量,他就是实例变量。变量也可以叫做成员,没什么区别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package cn.xwiz.lab.jvm.Static;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) {
		ClassA a1 = new ClassA();
		ClassA a2 = new ClassA();
		ClassA a3 = new ClassA();
		a1.doNothing();
		a2.doNothing();
		a3.doNothing();
		try {
			new BufferedReader(new InputStreamReader(System.in)).readLine();
		} catch (IOException e) {
		}
	}
}

main主程序中,创建三个实例(三个ClassA的具体对象)。根据前面的啰嗦,一定能够猜到,在heap中存在a1, a2, a3三个对象,每个对象持有一份s2实例变量,并且每个s2的实例变量的内存地址一定不同。

因此在内存堆中,清晰地列出了三个实例的三个实例变量。

但是三个实例并没有列出那个99999的字符串数组。它肯定不再heap堆中,因为它在方法区中。注意看cn.xwiz.lab.jvm.Static.ClassA前面的”class”标识字符。

方法区,在逻辑上和堆紧密联系,但又是一个特殊的区,一般叫做non-heap非堆,它保存虚拟机的类加载信息,常量和静态变量等,所有的线程都共享这块区域。在上面的第一张图中,如果点开cn.xwiz.lab.jvm.Static.ClassA,就能看到Class的类变量,拥有相同的内存地址:0x9d50000

This post is licensed under CC BY 4.0 by the author.