锁定老帖子 主题:Java变量作用域内存
精华帖 (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、局部变量定义在循环体内外,仅仅对代码的可读性有影响。对代码执行没有区别。 |
|
返回顶楼 | |
发表时间: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(); } 运行结果不变。 |
|
返回顶楼 | |