Asice
V2EX  ›  Java

jvm 内存分析,服务器内存不足会导致 Java 程序卡死吗

  •  
  •   Asice · Dec 4, 2018 · 5570 views
    This topic created in 2740 days ago, the information mentioned may be changed or developed.

    visualVM 信息 tcp 信息,排除端口占用满了的问题

    因为卡的时候我看了控制台日志是服务器在 api 请求,然后日志打印也是卡住,2 秒打印一条信息。
    之前一直在 GC 导致 cpu100%,调了下 jvm 分配 5g,总 8g。mysql 和服务器用剩余 3g。
    现在 cpu 降到 20-50 了,但是还是卡死,内存不足的原因吗? jvm 内存给多了?

    24 replies    2018-12-25 18:29:12 +08:00
    sagaxu
        2
    sagaxu  
       Dec 4, 2018 via Android
    有 gc log 吗?
    peyppicp
        3
    peyppicp  
       Dec 4, 2018
    这 jvm cpu 占用才 1%。考虑下是不是线程阻塞在业务逻辑上了。
    这种 cpu 占用,要么没请求量,要么都阻塞了。
    jstack 看一哈
    Asice
        4
    Asice  
    OP
       Dec 4, 2018
    @peyppicp 之前 jvm 默认没带参数,直接 GC 100cpu,现在分配堆内存 5g 还是卡死,但是不是 GC 卡死了。现在分配改 4g,应该还是卡死。
    现在推测
    1.内存不足
    2.带宽问题,但是我 ping 是没问题,只是阿里云监控带宽是占满的
    fmumu
        5
    fmumu  
       Dec 4, 2018 via Android
    gc 太频繁了吧
    Asice
        6
    Asice  
    OP
       Dec 4, 2018
    @peyppicp 不应该是堵塞,线程数都没上去,峰值 600 多的线程数
    Asice
        7
    Asice  
    OP
       Dec 4, 2018
    @fmumu 之前就是 gc 频繁 cpu100,现在分配堆内存就没 100%问题了
    peyppicp
        8
    peyppicp  
       Dec 4, 2018
    带宽跑满 瓶颈在网络 IO 啊。
    用 iftop 命令看一下,是不是 jvm 把服务器带宽跑满
    AiLinkLife
        9
    AiLinkLife  
       Dec 4, 2018
    程序卡死内存过高 jvm 内存不要设置太高影响机器性能找到你垃圾回收机制频繁的原因,频繁回收会导致程序卡顿
    pursuer
        10
    pursuer  
       Dec 4, 2018
    会是有内存泄漏吗?
    szq8014
        11
    szq8014  
       Dec 5, 2018
    怎么个卡死法? jstack 看看线程们都在干什么
    Asice
        12
    Asice  
    OP
       Dec 5, 2018
    @szq8014 目前 cpu 很低,我也不知道 jstack 能看什么,之前 100% 还能根据线程 id 看什么线程导致 100%。现在 cpu 没问题了,jstack 感觉就没切入点了。
    目测带宽问题,做了多线程图片中转
    Asice
        13
    Asice  
    OP
       Dec 5, 2018
    @AiLinkLife jvm 参数慢慢调吧,这个东西也没人教你的,都是自己慢慢尝试的
    szq8014
        14
    szq8014  
       Dec 5, 2018
    @Asice 看线程有没有在等 lock 啥的,万一不是服务器的锅而是代码有问题呢~
    Asice
        15
    Asice  
    OP
       Dec 5, 2018
    @szq8014
    jstack 78 个线程,只有 3 种状态,RUNNABLE,WAITING,TIMED_WAITING。
    现在也排除带宽问题了,刚卡的时候带宽不到 1m
    见鬼,难道 gc 的问题
    Asice
        16
    Asice  
    OP
       Dec 5, 2018
    Locked ownable synchronizers:
    - locked <34e8f9d1> (a java.util.concurrent.ThreadPoolExecutor$Worker)
    好像是线程池死锁了
    Asice
        17
    Asice  
    OP
       Dec 5, 2018
    但是我不明白的问题是就算死锁了,cpu 占用不高,线程也才 78 个。不是应该还能运行。
    这个线程池是独立的一个部分,不会影响业务的,业务的线程应该还是能运行的
    luosuosile
        18
    luosuosile  
       Dec 5, 2018
    如果你是频繁 gc,应该是老年代内存分配不足,
    老年代内存分配不足,会导致 fullgc 过多,这种 gc 耗时很长,会让整个 jvm 的程序停下来。
    你直接增加 jvm 内存,jvm 会不会增大老年代的内存并不知道。
    你应该增加 jvm 合适的内存大小,然后输入 jvm 指令增大老年代内存。这样应该可以解决频繁 gc 的问题。
    如果明显有效果,之后能跑就可以不用动了。
    但是感觉还不够就再调整新生代以及新生代的两个 surrvior 区的比例。
    luosuosile
        19
    luosuosile  
       Dec 5, 2018
    我也就一年经验,没有调试过 jvm,但是看过深入了解 jvm,所以就参考一下吧。最喜欢楼主这种能学到东西的帖子了
    也许你该把 jvm 的内存分配信息发出来给大家看。
    q397064399
        20
    q397064399  
       Dec 5, 2018
    @luosuosile #18 应该先定位一下 什么对象创建了这么多年 而且会进入老年代,进入老年代 都是老油子 在 minor GC 下活下来好几次的老家伙
    luosuosile
        21
    luosuosile  
       Dec 5, 2018
    @q397064399 嗯,有什么可以查看老年代里的对象名的方法呢。

    因为基本一直要用的老家伙占满了老年代空间,新的想进来的进不来所以频繁 gc。没毛病
    szq8014
        22
    szq8014  
       Dec 6, 2018
    @Asice
    jstack  就看看有没有主要的线程在等锁导致卡

    内存方面可以试试:

    装个 visual GC  插件方便看各代的内存状况


    还能对内存进行采样,然后过滤包名看看啥对象多



    然后把图发上来给大家围观下
    dezhou9
        23
    dezhou9  
       Dec 23, 2018 via Android
    学习了
    Asice
        24
    Asice  
    OP
       Dec 25, 2018
    结帖,循环中没有休眠,虽然不是死循环,但是某个时间点线程一多会把带宽占满(多线程中转图片)。
    所以虽然是多线程引起的,但是不是 cpu100%问题。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1287 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 17:22 · PVG 01:22 · LAX 10:22 · JFK 13:22
    ♥ Do have faith in what you're doing.