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 循环后,停顿一分钟内存依然没被回收。
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
说明内存够,不需要进行回收
|