Fra*_*ank 2 garbage-collection jvm spark-streaming
我的 Spark Streaming 程序中 GC 时间太长。在GC日志中,我发现有人System.gc()在程序中调用了。我不调用System.gc()我的代码。所以调用者应该是我使用的api。
我添加-XX:-DisableExplicitGC到 JVM 并修复了这个问题。不过,我想知道是谁打电话的System.gc()。
我尝试了一些方法。
jstack。但GC不是那么频繁,很难转储调用该方法的线程。java.lang.System.gc()。但这似乎不起作用。我如何知道谁在spark流程序中调用了System.gc()?
您不会发现System.gc,jstack因为在 stop-the-world 暂停期间,JVM 不接受来自 Dynamic Attach 工具的连接,包括jstack、jmap和jcmd类似工具。
可以使用async-profilerSystem.gc跟踪调用者:
预先开始分析:
$ profiler.sh start -e java.lang.System.gc <pid>
Run Code Online (Sandbox Code Playgroud)发生一种或多种System.gc情况后,停止分析并打印堆栈跟踪:
$ profiler.sh stop -o traces <pid>
Run Code Online (Sandbox Code Playgroud)
输出示例:
--- 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
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,System.gc从两个地方调用了 6 次。这两种情况都是 JDK 内部强制进行垃圾回收的典型情况。
第一个来自java.nio.Bits.reserveMemory. 当没有足够的可用内存来分配新的直接 ByteBuffer 时(由于-XX:MaxDirectMemorySize限制),JDK 会强制进行 Full GC 回收无法访问的直接 ByteBuffer。
第二个来自 GC Daemon 线程。这由 Java RMI 运行时定期调用。例如,如果您使用 JMX 远程,则每小时自动启用一次定期 GC。这可以通过-Dsun.rmi.dgc.client.gcInterval系统属性进行调整。