有关JVM的GC问题

发布于 2021-11-21 11:29:52 字数 1507 浏览 938 评论 13

import java.util.ArrayList;  
import java.util.List;  
  
public class Test {  
  
    private byte[] buffer;  
    private List ls;  
  
    public Test() {  
        this.buffer = new byte[4 * 1024 * 1024];  
        this.ls = new ArrayList();  
    }  
  
    private List getList() {  
        return ls;  
    }  
  
    public static void main(String[] args) {  
        Test t1 = new Test();  
        Test t2 = new Test();  
        t1.getList().add(t2);  
        t2.getList().add(t1);  
        t1 = t2 = null;  
        Test t3 = new Test(); 
        System.gc();
        System.out.println(t3);  
    }  

}

用以下参数运行java -Xms10M -Xmx10M Test,将jvm的大小设置为10M,不允许扩展,按引用计数法,t1和t2相互引用,他们的引用计数都不可能为0,那么他们将永远不会回收,在我的环境中JVM共10M,t1 t2占用8m,如果是引用计数那么剩下的2M,是不足以创建t3的,会抛出异常。我运行时果然抛出了异常,难道这说明我的JVM真的用的引用计数进行垃圾回收的?(我用的是java version "1.7.0_10" Java HotSpot(TM) Client VM),求解释哦!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

吃颗糖壮壮胆 2021-11-23 15:26:24

 CG 回收 法则第一点是  null 并且 长时间不使用的时候会回收 第二点new 对象 已经好长时间没时间 那也会回收

猫烠⑼条掵仅有一顆心 2021-11-23 15:26:04

java gc不是引用计数, 是根搜索法确定是否可以回收!

第二System.gc()有没有都没有关系,java会在 heap不够分配的时候触发gc。

第三,理论这不会oom,因为java是能够回收t1,t2。我在 win java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)

运行也确实没有oom。去掉t1=t2=null,会heap oom 

第四,java不是 你new byte[4 * 1024 * 1024]这么大,就是占用这么多内存,实际会比这个大,因为还有object header,object的一些占用,字节对齐等!

下午回来在测试下你说的,你是在win上运行还是,unix运行?是在哪一行oom的?

柳絮泡泡 2021-11-23 15:25:51

还是好好看看jvm基础吧,你以为引用计数就是只要有个引用就不能回收?

草莓味的萝莉 2021-11-23 15:25:45

java内存特征:

别指望在java程序里精确控制内存回收,既不能达到目标,而且往往事与愿违,当你越是想通过gc解决问题是反而制造问题。当gc不存在是最好的策略。

java使用内存杜绝一次申请大量内存,尤其是数组。实际上你的代码在第个test创建就已经挂了,你有10M,但是一个两个4M的数组足够造成内存泄漏。

牵你的手,一向走下去 2021-11-23 15:24:06

具体叫啥名忘了

情场扛把子 2021-11-23 15:23:43

应该是引用计数,应该不是那个啥挂在树上的。

柠檬 2021-11-23 15:21:04

你的代码里就有对象的相互引用,就跟内存泄漏一样,没法gc掉,所以引用一直会存在,new第三个的时候,系统内存最大值已经设定,又无法执行gc,所以才会出错的。关于垃圾可以看下jvm的书,gc是按几个年代来回收的,采用的算法也不一样的

静谧 2021-11-23 15:10:42

jvm不是用的引用计数法,而且System.GC()好像只是标记,什么时候真正GC好像还是jvm说了算,我也忘了,不知道对不对

谢绝鈎搭 2021-11-23 15:06:27

System.gc(),也是不确定的,而且还可以禁止显示调用.

本宫微胖 2021-11-23 14:50:19

在win上

少女情怀诗 2021-11-23 14:38:45

java gc不是引用计数, 是根搜索法确定是否可以回收!

第二System.gc()有没有都没有关系,java会在 heap不够分配的时候触发gc。

第三,理论这不会oom,因为java是能够回收t1,t2。我在 win java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)

运行也确实没有oom。去掉t1=t2=null,会heap oom 

第四,java不是 你new byte[4 * 1024 * 1024]这么大,就是占用这么多内存,实际会比这个大,因为还有object header,object的一些占用,字节对齐等!

下午回来在测试下你说的,你是在win上运行还是,unix运行?是在哪一行oom的?

柒夜笙歌凉 2021-11-23 14:30:57

nice work!用 dump oom error是一种好的分析方法,也可以,用jstat,debug分析,看old和new的使用情况!当然还可以用其他分享工具!

甜柠檬 2021-11-23 10:56:33

以下是运行的时候堆分析

try{
    Thread.sleep(100000000);
}catch(Exception e){
}
Test t1 = new Test();   
Test t2 = new Test(); 

C:UsersAdministrator>jmap -heap 5028
Attaching to process ID 5028, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.45-b08

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 10485760 (10.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 2621440 (2.5MB)
   used     = 678072 (0.6466598510742188MB)
   free     = 1943368 (1.8533401489257812MB)
   25.86639404296875% used
From Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
PS Old Generation
   capacity = 7340032 (7.0MB)
   used     = 0 (0.0MB)
   free     = 7340032 (7.0MB)
   0.0% used
PS Perm Generation
   capacity = 22020096 (21.0MB)
   used     = 2488384 (2.37310791015625MB)
   free     = 19531712 (18.62689208984375MB)
   11.300513857886905% used

可以看出Old Gen 只有7M,你t2 new的时候内存已经不足了。

Test t1 = new Test(); 
try{
    Thread.sleep(100000000);
}catch(Exception e){
}  
Test t2 = new Test(); 

C:UsersAdministrator>jmap -heap 3356
Attaching to process ID 3356, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.45-b08

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 10485760 (10.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 2621440 (2.5MB)
   used     = 678072 (0.6466598510742188MB)
   free     = 1943368 (1.8533401489257812MB)
   25.86639404296875% used
From Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
PS Old Generation
   capacity = 7340032 (7.0MB)
   used     = 4194320 (4.0000152587890625MB)
   free     = 3145712 (2.9999847412109375MB)
   57.143075125558035% used
PS Perm Generation
   capacity = 22020096 (21.0MB)
   used     = 2488392 (2.3731155395507812MB)
   free     = 19531704 (18.62688446044922MB)
   11.300550188337054% used

1501 interned Strings occupying 138800 bytes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文