V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
CodeXx
V2EX  ›  Java

请教一个 Java 内存占用的问题

  •  
  •   CodeXx · 2020-03-04 14:26:49 +08:00 · 5216 次点击
    这是一个创建于 1485 天前的主题,其中的信息可能已经有所发展或是发生改变。
    跑着的 Java 程序突然开始频繁报 java.lang.OutOfMemoryError: Java heap space 错误,应该是内存不足。想查一下是哪里有内存泄漏,用 jmap -heap 查到堆占用也就 1g 左右。但是任务管理器中这个程序占了 2g 多内存。用 jconsole 查看非堆内存也就占了 100MB,想问下还有 1g 多内存是从哪里产生的,这种问题还有什么好的方法可以排查吗

    Heap Configuration:
    MinHeapFreeRatio = 0
    MaxHeapFreeRatio = 100
    MaxHeapSize = 2128609280 (2030.0
    NewSize = 44564480 (42.5MB)
    MaxNewSize = 709361664 (676.5MB
    OldSize = 89653248 (85.5MB)
    NewRatio = 2
    SurvivorRatio = 8
    MetaspaceSize = 21807104 (20.79687
    CompressedClassSpaceSize = 1073741824 (1024.0
    MaxMetaspaceSize = 17592186044415 MB
    G1HeapRegionSize = 0 (0.0MB)

    Heap Usage:
    PS Young Generation
    Eden Space:
    capacity = 380633088 (363.0MB)
    used = 142412024 (135.81468963623047MB)
    free = 238221064 (227.18531036376953MB)
    37.41451505130316% used
    From Space:
    capacity = 153092096 (146.0MB)
    used = 98938800 (94.35539245605469MB)
    free = 54153296 (51.64460754394531MB)
    64.62698113428404% used
    To Space:
    capacity = 160956416 (153.5MB)
    used = 0 (0.0MB)
    free = 160956416 (153.5MB)
    0.0% used
    PS Old Generation
    capacity = 1143472128 (1090.5MB)
    used = 856911104 (817.214111328125MB)
    free = 286561024 (273.285888671875MB)
    74.9393958118409% used

    31023 interned Strings occupying 3682496 bytes.
    第 1 条附言  ·  2020-03-04 22:22:56 +08:00
    2020-03-04 01:08:55.525 [HikariPool-1 housekeeper] WARN c.z.hikari.pool.HikariPool - HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=1m5s643ms48?s450ns).
    2020-03-04 01:09:08.516 [task-11] ERROR o.s.s.s.TaskUtils$LoggingErrorHandler - Unexpected error occurred in scheduled task.
    java.lang.OutOfMemoryError: Java heap space
    at java.awt.image.DataBufferByte.<init>(Unknown Source)
    at java.awt.image.Raster.createInterleavedRaster(Unknown Source)
    at java.awt.image.BufferedImage.<init>(Unknown Source)
    at net.coobird.thumbnailator.builders.BufferedImageBuilder.build(Unknown Source)
    at net.coobird.thumbnailator.makers.ThumbnailMaker.makeThumbnail(Unknown Source)
    at net.coobird.thumbnailator.makers.FixedSizeThumbnailMaker.make(Unknown Source)
    at net.coobird.thumbnailator.Thumbnailator.createThumbnail(Unknown Source)
    at net.coobird.thumbnailator.Thumbnails$Builder.toOutputStream(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor63.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    还有
    java.lang.OutOfMemoryError: GC overhead limit exceeded
    12 条回复    2020-03-05 17:45:43 +08:00
    nickchenyx
        1
    nickchenyx  
       2020-03-04 15:21:38 +08:00
    看你这个打印有点问题啊,你的 From&To Space 占用太高了,young gen 里,From&To 和 eden 的比例应该是 2:8,你这个不要修改默认配置。

    这里看你的 heap usage 没啥问题啊,在 jvm 启动的时候加上参数打印一下在 gc 的时候以及 oom 的时候内存分布情况

    -XX:ErrorFile=./hs_err_pid%p.log -XX:HeapDumpPath=./ -Xloggc:./gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps
    jiashun
        2
    jiashun  
       2020-03-04 15:27:00 +08:00
    看程序 GC 正常不,如果 GC 正常,没有频繁 GC (堆内存对象正常回收),可以把目光转向非堆内存,排查下哪里用到了 NIO,有没内存泄露
    yidinghe
        3
    yidinghe  
       2020-03-04 15:33:41 +08:00
    如果光看总量看不出问题,那么就要把内存 dump 出来看具体哪些对象占用了内存
    yanyueio
        4
    yanyueio  
       2020-03-04 15:42:13 +08:00
    与上面几位大佬说的基本思路一致,主要看 GC 是否正常(一般就是这里),不行的话在看具体的对象占用内存量。

    个人觉得栈的话一般不用看,至少我还没有遇到过栈空间问题。

    补一补 JVM 的知识吧,类似于搞 C/C++ 的必须知道进程的结构一样。
    CodeXx
        5
    CodeXx  
    OP
       2020-03-04 16:59:49 +08:00
    @nickchenyx
    @jiashun
    @yidinghe
    @yanyueio
    感谢各位提供思路
    CodeXx
        6
    CodeXx  
    OP
       2020-03-04 17:59:54 +08:00
    @yidinghe dump 出来的文件 1g 多,内存占用高的是 org.apache.mina.transport.socket.nio.NioSocketSession 占了 400 多 m。但程序系统占用了 2g 多,感觉还有一部分内存没有查看到
    liuming
        7
    liuming  
       2020-03-04 18:36:33 +08:00
    看 heap usage,实际堆空间显示还有不少空闲,当需要在堆上分配空间的时候不该出现 OOM: Java heap space 这样的错误提示,除非系统的空闲内存不足了,也就是堆外内存有泄漏、终于耗尽了系统的剩余内存,可是如果是这种情况,系统的表现不该是死机之类的么?
    CodeXx
        8
    CodeXx  
    OP
       2020-03-04 19:27:02 +08:00
    @liuming 抱歉忘了说,这个是没报错的时候打印的
    gaius
        9
    gaius  
       2020-03-04 19:27:18 +08:00 via Android
    日志里打印的是什么样的,mina netty 这种多和堆外泄露有关,netty 的话会抛自己的异常,mina 不清楚,而且也不该是 heap space。
    CodeXx
        10
    CodeXx  
    OP
       2020-03-04 22:22:05 +08:00
    @gaius 确实可能是堆外的,我手动 gc 后堆内存只占几十 m 了,但是程序占内存还是 2g。日志报的错贴出来了,请问大佬这种堆外泄漏要怎么查啊。
    liuming
        11
    liuming  
       2020-03-05 00:15:30 +08:00
    看了下 Thumbnailator 在 github 上的 issue,不少堆上出 OOM 的……比如 https://github.com/coobird/thumbnailator/issues/111,根据这 issue 里作者的说法,Thumbnailator 挺耗内存的,尤其是你这貌似在多线程使用……不过这应该不是程序内存占用远远大于堆实际占用的原因,但应是导致 OOM 的原因。怎么排查堆外泄漏可以参考下这个视频,视频里介绍了不少实际工具:
    CodeXx
        12
    CodeXx  
    OP
       2020-03-05 17:45:43 +08:00
    @liuming 好的,感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4084 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 05:21 · PVG 13:21 · LAX 22:21 · JFK 01:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.