首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么GC不在相同的方法中运行

为什么GC不在相同的方法中运行
EN

Stack Overflow用户
提问于 2019-06-09 17:08:41
回答 1查看 1.2K关注 0票数 -1

我正在使用gc,当gc(我使用并行gc)没有涉及时,我发现了一些有趣的情况,这是我的代码

代码语言:javascript
复制
public static void main(String[] args) {
       System.out.println(Runtime.getRuntime().freeMemory() / (1024 * 1024) + " free");

    String[] strings = new String[(40 * 1024 * 1024) / Integer.BYTES];
    System.out.println(strings.length);

    System.out.println(Runtime.getRuntime().freeMemory() / (1024 * 1024) + " free");

    strings = new String[(40 * 1024 * 1024) / Integer.BYTES];
    System.out.println(strings.length);

    System.out.println(Runtime.getRuntime().freeMemory() / (1024 * 1024) + " free");

    }

我的Java版本是:

代码语言:javascript
复制
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

该程序涉及以下argc:

代码语言:javascript
复制
-Xmx64m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps

这是输出:

代码语言:javascript
复制
59 free
10485760
19 free
2019-06-09T14:53:18.868+0600: 0.105: [GC (Allocation Failure) [PSYoungGen: 1640K->480K(18944K)] 42600K->41448K(62976K), 0.0018199 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2019-06-09T14:53:18.870+0600: 0.107: [Full GC (Ergonomics) [PSYoungGen: 480K->0K(18944K)] [ParOldGen: 40968K->41339K(44032K)] 41448K->41339K(62976K), [Metaspace: 3033K->3033K(1056768K)], 0.0174681 secs] [Times: user=0.04 sys=0.00, real=0.02 secs] 
2019-06-09T14:53:18.888+0600: 0.125: [GC (Allocation Failure) [PSYoungGen: 0K->0K(18944K)] 41339K->41339K(62976K), 0.0017270 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2019-06-09T14:53:18.889+0600: 0.126: [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(18944K)] [ParOldGen: 41339K->41321K(44032K)] 41339K->41321K(62976K), [Metaspace: 3033K->3033K(1056768K)], 0.0140842 secs] [Times: user=0.03 sys=0.01, real=0.01 secs] 
Heap
 PSYoungGen      total 18944K, used 491K [0x00000000feb00000, 0x0000000100000000, 0x0000000100000000)
  eden space 16384K, 3% used [0x00000000feb00000,0x00000000feb7afa0,0x00000000ffb00000)
  from space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
  to   space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
 ParOldGen       total 44032K, used 41321K [0x00000000fc000000, 0x00000000feb00000, 0x00000000feb00000)
  object space 44032K, 93% used [0x00000000fc000000,0x00000000fe85a6d0,0x00000000feb00000)
 Metaspace       used 3064K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 336K, capacity 388K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at lightbox.GcWIthoutComp.main(GcWIthoutComp.java:11)

根据日志,JVM不能为字符串第二次分配内存,但是如果我添加JVM arg -Xcomp,它将工作并提供以下输出

代码语言:javascript
复制
59 free
10485760
19 free
2019-06-09T15:01:06.593+0600: 0.830: [GC (Allocation Failure) [PSYoungGen: 1982K->512K(18944K)] 42942K->41480K(62976K), 0.0008554 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
2019-06-09T15:01:06.594+0600: 0.831: [Full GC (Ergonomics) [PSYoungGen: 512K->0K(18944K)] [ParOldGen: 40968K->411K(37376K)] 41480K->411K(56320K), [Metaspace: 3377K->3377K(1056768K)], 0.0100865 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 
10485760
20 free
Heap
 PSYoungGen      total 18944K, used 1147K [0x00000000feb00000, 0x0000000100000000, 0x0000000100000000)
  eden space 16384K, 7% used [0x00000000feb00000,0x00000000fec1ed48,0x00000000ffb00000)
  from space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 44032K, used 41371K [0x00000000fc000000, 0x00000000feb00000, 0x00000000feb00000)
  object space 44032K, 93% used [0x00000000fc000000,0x00000000fe866c90,0x00000000feb00000)
 Metaspace       used 3399K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 334K, capacity 388K, committed 512K, reserved 1048576K

据我所知,在检测未使用的内存方面,编译后的代码对于GC来说要舒服得多。此外,如果我删除-Xcomp并将数组创建移到单独的方法中,它不会抛出OOM异常:

代码语言:javascript
复制
public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().freeMemory() / (1024 * 1024) + " free");

        allocate();

        System.out.println(Runtime.getRuntime().freeMemory() / (1024 * 1024) + " free");
        allocate();
        System.out.println(Runtime.getRuntime().freeMemory() / (1024 * 1024) + " free");

    }

    private static void allocate() {
        String[] strings = new String[(40 * 1024 * 1024) / Integer.BYTES];
        System.out.println(strings.length);
    }

我的问题是:

  1. 如上所示,-Xcomp为什么使用分配解决问题?
  2. 为什么将分配移动到独立方法解决了我的问题?

如果你有有用的链接,请在评论中提供。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-09 17:55:16

注释只放在一行中,很难解释其中的内容。重要的区别似乎在于,使用-Xcomp时,已经可以收集本地变量字符串。所以你会得到:

代码语言:javascript
复制
2019-06-09T15:01:06.593+0600: 0.830: [GC (Allocation Failure) [PSYoungGen: 1982K->512K(18944K)] 42942K->41480K(62976K), 0.0008554 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
2019-06-09T15:01:06.594+0600: 0.831: [Full GC (Ergonomics) [PSYoungGen: 512K->0K(18944K)] [ParOldGen: 40968K->411K(37376K)] 41480K->411K(56320K), [Metaspace: 3377K->3377K(1056768K)], 0.0100865 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 

所以你会得到一个分配失败,但是GC可以释放足够的内存。

如果没有-Xcomp,则无法收集loal变量字符串,因此您得到的消息类似于:

代码语言:javascript
复制
2019-06-09T14:53:18.868+0600: 0.105: [GC (Allocation Failure) [PSYoungGen: 1640K->480K(18944K)] 42600K->41448K(62976K), 0.0018199 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2019-06-09T14:53:18.870+0600: 0.107: [Full GC (Ergonomics) [PSYoungGen: 480K->0K(18944K)] [ParOldGen: 40968K->41339K(44032K)] 41448K->41339K(62976K), [Metaspace: 3033K->3033K(1056768K)], 0.0174681 secs] [Times: user=0.04 sys=0.00, real=0.02 secs] 
2019-06-09T14:53:18.888+0600: 0.125: [GC (Allocation Failure) [PSYoungGen: 0K->0K(18944K)] 41339K->41339K(62976K), 0.0017270 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2019-06-09T14:53:18.889+0600: 0.126: [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(18944K)] [ParOldGen: 41339K->41321K(44032K)] 41339K->41321K(62976K), [Metaspace: 3033K->3033K(1056768K)], 0.0140842 secs] [Times: user=0.03 sys=0.01, real=0.01 secs] 

这表明GC试图释放内存,但无法完成。

(看看PSYoungGen:它显示了内存是如何关闭的。当它在没有-Xcomp的情况下失败时,几乎没有什么是可能的。使用-Xcomp,它从1982K下降到512K。另请参阅https://dzone.com/articles/understanding-garbage-collection-log)

我找不到-Xcomp正在做的事情。所以,很抱歉,我现在只能给你们解释一下日志。因此,这就像在分配新生成的数组之前将字符串设置为null一样。因此,如果在第二次为数组赋值之前添加一个字符串= null;:即使没有-Xcomp,您也会得到大致相同的gc消息。

关于在方法中使用它:你的方法中有一个局部变量。因此,你赋值数组,然后方法结束,垃圾收集器可以收集局部变量。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56513329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档