我怎么知道谁在Spark Streaming程序中调用System.gc()?

问题描述 投票:0回答:1

我的火花流程序中GC时间太长。在GC日志中,我发现有人在程序中称为System.gc()。我没有在代码中调用System.gc()。因此,调用方应该是我使用的api。

我将-XX:-DisableExplicitGC添加到JVM并解决此问题。但是,我想知道谁叫System.gc()

我尝试了一些方法。

  1. 使用jstack。但是GC并不是那么频繁,很难转储调用该方法的线程。
  2. 我在JProfiler中调用方法java.lang.System.gc()时添加了添加线程转储的触发器。但这似乎不起作用。

我怎么知道谁在Spark Streaming程序中调用System.gc()?

garbage-collection jvm spark-streaming
1个回答
0
投票

您不会用System.gc捕获jstack,因为在世界暂停期间JVM不接受来自动态附加工具的连接,包括jstackjmapjcmd等。

可以通过System.gc跟踪async-profiler呼叫者:

  1. 事先开始分析:

    $ profiler.sh start -e java.lang.System.gc <pid>
    
  2. 发生一个或多个System.gc之后,停止分析并打印堆栈跟踪:

    $ profiler.sh stop -o traces <pid>
    

    示例输出:

    --- Execution profile ---
    Total samples       : 6
    
    Frame buffer usage  : 0.0007%
    
    --- 4 calls (66.67%), 4 samples
      [ 0] java.lang.System.gc
      [ 1] java.nio.Bits.reserveMemory
      [ 2] java.nio.DirectByteBuffer.<init>
      [ 3] java.nio.ByteBuffer.allocateDirect
      [ 4] Allocate.main
    
    --- 2 calls (33.33%), 2 samples
      [ 0] java.lang.System.gc
      [ 1] sun.misc.GC$Daemon.run
    

    在上述示例中,System.gc从两个位置被调用6次。这两种都是JDK内部强制垃圾收集的典型情况。

    第一个来自java.nio.Bits.reserveMemory。当没有足够的可用内存来分配新的直接ByteBuffer时(由于[C​​0]限制),JDK会强制完整GC回收无法访问的直接ByteBuffer。

    第二个来自GC守护程序线程。 Java RMI运行时会定期调用此方法。例如,如果您使用JMX远程,则每小时会自动启用一次定期GC。可以使用-XX:MaxDirectMemorySize系统属性进行调整。

© www.soinside.com 2019 - 2024. All rights reserved.