【问题标题】:Java G1 Garbage collector takes a lot of memoryJava G1 垃圾收集器占用大量内存
【发布时间】:2019-02-08 09:16:32
【问题描述】:

我有大型数据库的项目。为了解析它,我使用带有 G1 垃圾收集器的 java。 当程序运行很长时间时,java开始消耗大量内存。 但是当我检查java堆时,大小要小得多。例如:

  • Java 占用 20 Gb 的 RAM
  • “jmap -histo” - 显示堆大约有 5 Gb 的 RAM

问题:什么占用了我剩余的 RAM?这是G1的开销吗?

编辑:这里是统计数据

java procces:分配 ~50gb,消耗 ~20gb
jmap 信息:堆大小 ~4gb

【问题讨论】:

  • 这就是 JVM 堆的工作方式,您将 -Xmx-Xms 指定为 20GB,当前只需要 5GB...
  • @Eugene 我说的是显式 RAM 消耗,-Xmx40G,java 消耗 20G 但堆大小只有 4G
  • 哦,所以进程本身消耗20G,堆只有4个?你是怎么测量这 20 个的?
  • @Eugene 我使用“htop”来监控进程,我添加了一些图片来展示
  • 是的 20Gb 是“当前状态”。当前状态有历史。当它一次需要 20Gb 时,它必须分配该数量的内存,当它不再需要它时,即包含的对象已被垃圾收集,不了解 Java 堆的外部工具将继续说这个过程已分配了该数量的内存。而在 JVM 内部,大部分内存被认为是空闲的,准备好被新对象填充。 • 堆外内存可以包括直接字节缓冲区。只要可用 RAM 允许,您可以拥有尽可能多和尽可能大的空间。

标签: java garbage-collection g1gc


【解决方案1】:

我理解问题所在。正如@Holger 提到的,内存被分配给java进程但没有完全填满堆。但是G1分配这么多内存的原因

如果 G1 需要分配很多巨大的区域,它就会受到影响。每次对象大小 > 区域大小的 50% 时都会创建它们。他们将浪费空间,因为该地区不会创造任何其他东西。因此,如果它的大小为 51%,您将浪费该区域的 49%。更糟糕的是,如果一个区域是 2MB,而你的对象是 2.1MB,那么它会在第二个区域浪费 1.9MB。如果分配大对象,请调整 XX:G1HeapRegionSize。

【讨论】:

    【解决方案2】:

    RAM 消耗将是由于庞大的数据库大小结果集的大小

    试试下面的: 优化垃圾回收:

    • 小心字符串连接运算符 (+) 使用 concat() 代替

    • 如果使用 spring,尝试 setFetchSize(一次要获取的行数) 但是,使用 setFetchSize 会增加您的执行时间,但它会节省内存

    • 删除所有不必要的语句

    • 使用异步执行

    【讨论】:

    • 感谢您的回答。但我没有同时读取整个数据库。我使用分页:1)读取少量数据 - 块; 2)处理它; 3)保存到数据库。它不应该占用这么多 Gb 的 RAM。而最神秘的——堆比所有的内存消耗都小。问题 - 如果不是堆,什么会消耗这些内存?
    • 为什么您认为使用concat 比使用+ 运算符有什么优势?
    • @MadMan 这只是一个特定的场景,当您有两个项目要连接并且两个项目已经是 String 实例时。在这种情况下,String.concat 可能比使用StringBuilder 执行得更好,因为它的实现预先创建了一个正确大小的数组,并将输入字符串的两个普通副本复制到其中并使用该数组创建一个新的String 实例(不需要防御副本)。但是,JVM 专门针对典型的StringBuilder 使用进行了优化,并消除了开销。而 Java 9+ 将编译 + 运算符完全不同......
    • @Ani 您混淆了编译器的工作和运行时性能。您提到的所有分析都将在编译时完成,并且不会影响运行时性能。只要在参数处将String.concattoString() 组合在一起,它就会比+ 运算符更昂贵,因为这些中间String 实例需要内存并且意味着对字符内容进行额外的复制操作。我不知道,为什么你认为他们在使用concat 时是免费的,也许是魔法?
    • @MadMan 从 Java 9 开始,字符串连接运算符被编译为单个 invokedynamic 指令,该指令在运行时链接,因此,JRE 决定如何实现特定场景。因此,如果您使用带有两个字符串参数的+,它可能会链接到一些与String.concat 完全相同的代码。但更好的是,每个特定的星座都可以链接到专门的代码,在运行时动态生成。此外,如果认为有用,它可能会在后台实现缓存。等等……
    猜你喜欢
    • 2020-11-05
    • 2018-01-25
    • 2017-05-24
    • 1970-01-01
    • 2011-03-18
    • 2014-02-19
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多