
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) } impor 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 循环后,停顿一分钟内存依然没被回收。
1 sufan 2019-02-13 19:04:35 +08:00 via iPhone 清洁工还没有来 |
2 chenyu0x00 2019-02-13 19:07:35 +08:00 via Android go 和 java 的内存回收都不是实时进行的 |
3 myyou OP @chenyu0x00 不是实时进行的,也应该在一定时间内进行吧 |
4 alamaya 2019-02-13 19:13:30 +08:00 你需要 System.gc(),多运行几次 |
5 337136897 2019-02-13 19:13:32 +08:00 清洁工还没空来 |
6 lhx2008 2019-02-13 19:14:48 +08:00 via Android 内存回收需要暂停程序的,所以一般是到了阈值才回收,楼主可以用 System.gc()强制回收 |
7 chenyu0x00 2019-02-13 19:18:38 +08:00 via Android @myyou 毕竟内存回收是需要消耗算力的,而且 go 的内存回收还会暂停主程序,所以在内存充足的时候可以不进行内存回收。如果想要测试内存回收,你可以写一个函数,函数内部不断申请内存,然后在主函数不断调用该函数,看看程序的内存会不会无限增长。 |
8 myyou OP @chenyu0x00 把 sleep 时间拉长,的确有回收. @lhx2008 无论是 golang 的 runtime.gc()还是 java 的 System.gc(),直接调用都不回收内存,sleep 时间拉长的确有回收。 |
9 neoblackcap 2019-02-13 21:17:25 +08:00 via iPhone System.gc 只是给 JVM 提建议,JVM 完全可以不鸟你。都是符合规范的。比如 JVM 的堆有 1T 大,你才用了 1G 就调用 System.gc ,JVM 当然可以不鸟你。而且回收策略都不尽相同,你换成 G1 跟 ZGC 又不一样了 |
10 zwh2698 2019-02-13 22:33:28 +08:00 via Android 9 楼正解,gc 凭啥你说回收就回收呢?平衡策略怎么办? |
11 wweir 2019-02-14 05:47:55 +08:00 via Android 就这两份测试代码而言,今天我看到任何对堆栈的检测。如果没猜错的话,楼主是通过操作系统的命令来观测内存占用信息的。 程序从系统中分配的内存,与代码从 runtime 中分配的内存是两回事。 GC 只会把堆栈中的分配的内存交还给 runtime,而 runtime 中有内存复用的逻辑,具体什么时候交还给操作系统,有另外一套逻辑单独控制。 市面上介绍 runtime 的内存申请、复用、释放具体思想的书、文章很少,所以这一点经常会被人忽略 |
12 wweir 2019-02-14 05:49:53 +08:00 via Android 就这两份测试代码而言,我没有看到任何对堆栈的检测。 别字修正 |
13 snappyone 2019-02-14 09:33:00 +08:00 建议看下 gc 的触发原理,不是看时间跟 System.gc 调用的 |
14 micean 2019-02-14 09:51:42 +08:00 jvm 的信息都看不到 |
15 dosmlp 2019-02-14 10:12:07 +08:00 说明内存够,不需要进行回收 |