为什么创建的对象在离开作用域后没有被回收?

2019-02-13 17:45:38 +08:00
 myyou
import (
	"fmt"
	"time"
)

func main() {
	for i := 0; i < 10; i++ {
		c := make([]int32, 0, 1000000000)
		fmt.Println(len(c))
	}
	fmt.Println("====ok====")
	time.Sleep(60 * time.Second)
}
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class TestArray {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            ArrayList<Integer> al = new ArrayList<Integer>(1000000000);
            System.out.println(al.size());
        }

        System.out.println("====ok====");
        TimeUnit.MINUTES.sleep(1);
    }
}

这两个在做完 for 循环后,停顿一分钟内存依然没被回收。

2565 次点击
所在节点    Java
15 条回复
sufan
2019-02-13 19:04:35 +08:00
清洁工还没有来
chenyu0x00
2019-02-13 19:07:35 +08:00
go 和 java 的内存回收都不是实时进行的
myyou
2019-02-13 19:12:37 +08:00
@chenyu0x00 不是实时进行的,也应该在一定时间内进行吧
alamaya
2019-02-13 19:13:30 +08:00
你需要 System.gc(),多运行几次
337136897
2019-02-13 19:13:32 +08:00
清洁工还没空来
lhx2008
2019-02-13 19:14:48 +08:00
内存回收需要暂停程序的,所以一般是到了阈值才回收,楼主可以用 System.gc()强制回收
chenyu0x00
2019-02-13 19:18:38 +08:00
@myyou 毕竟内存回收是需要消耗算力的,而且 go 的内存回收还会暂停主程序,所以在内存充足的时候可以不进行内存回收。如果想要测试内存回收,你可以写一个函数,函数内部不断申请内存,然后在主函数不断调用该函数,看看程序的内存会不会无限增长。
myyou
2019-02-13 19:24:12 +08:00
@chenyu0x00 把 sleep 时间拉长,的确有回收.

@lhx2008 无论是 golang 的 runtime.gc()还是 java 的 System.gc(),直接调用都不回收内存,sleep 时间拉长的确有回收。
neoblackcap
2019-02-13 21:17:25 +08:00
System.gc 只是给 JVM 提建议,JVM 完全可以不鸟你。都是符合规范的。比如 JVM 的堆有 1T 大,你才用了 1G 就调用 System.gc ,JVM 当然可以不鸟你。而且回收策略都不尽相同,你换成 G1 跟 ZGC 又不一样了
zwh2698
2019-02-13 22:33:28 +08:00
9 楼正解,gc 凭啥你说回收就回收呢?平衡策略怎么办?
wweir
2019-02-14 05:47:55 +08:00
就这两份测试代码而言,今天我看到任何对堆栈的检测。如果没猜错的话,楼主是通过操作系统的命令来观测内存占用信息的。

程序从系统中分配的内存,与代码从 runtime 中分配的内存是两回事。
GC 只会把堆栈中的分配的内存交还给 runtime,而 runtime 中有内存复用的逻辑,具体什么时候交还给操作系统,有另外一套逻辑单独控制。

市面上介绍 runtime 的内存申请、复用、释放具体思想的书、文章很少,所以这一点经常会被人忽略
wweir
2019-02-14 05:49:53 +08:00
就这两份测试代码而言,我没有看到任何对堆栈的检测。

别字修正
snappyone
2019-02-14 09:33:00 +08:00
建议看下 gc 的触发原理,不是看时间跟 System.gc 调用的
micean
2019-02-14 09:51:42 +08:00
jvm 的信息都看不到
dosmlp
2019-02-14 10:12:07 +08:00
说明内存够,不需要进行回收

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/534637

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX