【问题标题】:java.lang.ref.Finalizer OutOfMemory After Memory Raise内存提升后的 java.lang.ref.Finalizer OutOfMemory
【发布时间】:2017-02-08 23:53:28
【问题描述】:

提取一个 heapdump 我意识到它有很多对象等待完成,其中大部分是来自 jdbc 连接等库的实例。

知道队列中的那些实例基本上是实现finalize() 的类,为什么它们根本没有最终确定?

几天前,我提出了这样一个实例的记忆。最初它有 1GB,新一代设置为 256 MB (-Xmx1g -XX:NewSize=256m -XX:MaxNewSize=256m)。随着我们添加了一些繁重的缓存功能,我们将分配给该实例的内存提高到 3 GB (-Xmx3G -XX:NewSize=512m -XX:MaxNewSize=512m)。从那一刻起,我们开始看到一些记忆。稍微调查了一下,我发现有很多 java.lang.ref.Finalizer 和等待终结的对象。

这怎么可能相互关联?它甚至可能相关吗?

【问题讨论】:

    标签: java memory out-of-memory finalizer


    【解决方案1】:

    为什么他们根本没有最终确定?

    某些组件需要更长的时间才能完成,尤其是涉及 IO 的任何事情。 JDBC 连接是相对较重的网络资源,因此它们需要更长的时间。

    我建议您使用连接池(大多数 JDBC 库都内置了它们)这样您就不会一直创建/销毁它们。

    注意:澄清1Gb = 1 千兆位或 128 MB(兆字节)256 mb 是 256 毫位或大约 1/4 位。 -XX:NewSize=512m 是 512 MB 而不是 256 MB。 -XX:MaxNewSize=512 不起作用,因为它只有 512 个字节,很可能您使用了 -XX:MaxNewSize=512m

    3Gb 是 3 GB,但假设您的意思是 3 GB,它不是 -Xmx1G,即 1 GB 或 8 Gb。

    【讨论】:

    • 我有点好奇这是怎么回事,为什么finalize()这个问题只有在内存更改后才弹出,这是否与我在新之间使用的配给有关?一代和老一代?
    • @FranciscoSpaeth 当您的内存较少时,您拥有的生成要完成的资源的应用程序会变慢。它可以是多线程的。如果你给它更多内存,它可以创建更多要清理的资源,但单线程终结器无法跟上,因此它成为瓶颈。简而言之,当您加快一点速度时,您会将性能问题转移到其他地方,可能会在此过程中破坏它。
    【解决方案2】:

    Object.finalize() 由垃圾收集器在清理的最后一步调用。 GC 会定期运行(取决于您使用的 GC,如果是 7 和 8,它可能是 CMS,或者 G1 如果您这样配置)。在“等待终结”中拥有大量对象可能意味着您有一个大堆和足够的内存,GC 不需要运行(CMS 最有可能,因为 G1 更频繁地运行微清理)。

    将 GC 跟踪添加到您的 JVM 启动参数并监控它的运行频率:-XX:+PrintGCDetails -XX:+PrintGCTimeStamps 请参阅:http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

    如果您使用大量堆 >1Gb 的小对象,您可能需要考虑使用 G1 垃圾收集器,因为它更适合此类任务并且没有 CMS 的“停止世界”行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-09
      • 2012-01-11
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多