论坛首页 Java企业应用论坛

Java变量作用域内存

浏览 11692 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (15) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-05-23  
zl198751 写道


所谓字节码完全相同而位置不一定,就说程序是一致的,我看很大程度上是不对的。
就是因为变量i和holdMemory在局部变量表的位置不同,所以程序在运行时的内存状态是不一致的。

当holdMemory定义在外面的话,循环结束后内存中依然保留为holdMemory开辟的内存。但是定义在里面的话内存在循环结束后就被回收了。


对于JVM而言,没有块级别的作用域,在进入方法体时,局部变量所占用的内存就已经在Java栈上分配好了,
直到方法结束,Java栈上的局部变量内存才被回收,不存在方法执行途中回收的问题。

不过要注意,这儿的内存仅仅是指Java栈上的内存(对于对象而言,也就是非primitive的变量,仅仅是对象的引用)
而Java对象所分配的内存,是位于Java堆中。

就楼主的例子,不论holdMemory定义在循环外、或者循环内,都不影响每一次循环中创建的new HoldMemory()的回收,因为,每一次循环的执行,都重写了同一个变量引用,从而导致上一次循环holdMemory对象引用的丢失,即原则上,每开始一个新的循环,上一个循环创建的holdMemory对象都是可回收的,这和holdMemory变量定义在循环体内外无关。



~~~~~~~~~~~~~~~~~~~~~~~
小结一下:
1、Java栈上的局部变量(primitive值、或者对象引用)所占用的内存,在方法结束后,随Java栈的回收而回收,与变量定义在循环体内外无关;
2、Java对象(使用堆内存)在每次循环后,自动丢弃上一次循环所保留的对象引用,从而该对象处于可回收状态。这也和变量定义在循环体内外无关;
3、局部变量定义在循环体内外,仅仅对代码的可读性有影响。对代码执行没有区别。
1 请登录后投票
   发表时间:2010-05-23  
这儿再做一个简单的试验,看一下:

public class Hello {
	void testMemory() throws Exception {
		logMemoryInfo();
		for (int i = 0; i < 1; i++) {
			Object ref = new int[500000];
		}
		logMemoryInfo();
	}

	void logMemoryInfo() throws Exception {
		System.out.print("before gc: usedmem: ");
		System.out.println(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
		System.gc();
		Thread.sleep(3000);
		System.out.print("after gc: usedmem: ");
		System.out.println(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
	}

	public static void main(String[] args) throws Exception {
		new Hello().testMemory();
	}
}


在我的机子上,运行结果如下:
before gc: usedmem: 215616
after gc: usedmem: 155336
before gc: usedmem: 2155352
after gc: usedmem: 137008

把上面的代码改成:
void testMemory() throws Exception {
	logMemoryInfo();
	Object ref;
	for (int i = 0; i < 1; i++) {
		ref = new int[500000];
	}
	logMemoryInfo();
}


运行结果不变。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics