现象:一个平时运行2小时的任务,突然一天还没跑完,看系统cpu、load都不算高,接口监控发现rt从平时几ms到几十ms增加到了几千ms。
起初怀疑线程被阻塞了,然后top -p -H查看线程,返现有一个运行时间远远大于其他线程,jstack 查找发现是cmsgc 线程。 于是jstat -gcutil ,吓了一跳 eden、old全都是100%, fullgc 几千次了。。。。
于是考虑jmap -dump:file=dump pid , 打算查找未释放的对象,但是应用内存4g多,不是我的小本能分析的了得。。 上火。
于是考虑重启应用,在内存占用还不是太高时dump出来进行分析。 在内存占用大约1.5g的时候,dump了一次,拖到本机(压缩一下,压缩率达到80%,网速不好时可以节省很多时间),mat分析一通,发现一个应用对象量格外大,那基本上跑不掉了。。
上btrace 跟踪在哪里产生的对象:
package com.sun.btrace.samples; import static com.sun.btrace.BTraceUtils.exit; import static com.sun.btrace.BTraceUtils.jstack; import static com.sun.btrace.BTraceUtils.println; import com.sun.btrace.annotations.BTrace; import com.sun.btrace.annotations.OnMethod; @BTrace public class MethodStackTrace { private static int printCount = 0; @OnMethod(clazz = "com.xxx.common.lang.diagnostic.Profiler", method = "/start/") public static void func() { if(printCount++ < 20){ println("=======stack======"); jstack(); println("########end#########"); } else exit(0); } }
一下就抓住了。。具体的就是业务代码的使用逻辑问题了。
另外, 当dump文件太大不好分析时,只是为了查看对象情况,可以直接使用 sudo -u admin jmap -histo:live `pgrep java` , 就能够按照内存占用量进行输出:
num #instances #bytes class name
----------------------------------------------
1: 263195 28174696 [C
2: 246862 25246080 [B
3: 144815 22059552 <constMethodKlass>
还有个加强版的工具TBMap,可以按内存分区输出对象占用量:
Object Histogram:
#num #all instances/bytes #eden instances/bytes #survivor instances/bytes #old instances/bytes #perm instances/bytes #Class description
-----------------------------------------------------------------------------------
1: 1459670/664283552 765458/85719080 75663/99027992 582912/476992632 35637/2543848 char[]
2: 325529/44662232 303670/27425504 13/136664 3773/14967256 18073/2132808 byte[]
3: 1301337/41642784 537975/17215200 75898/2428736 651827/20858464 35637/1140384 java.lang.String
4: 101777/39235776 80265/4929544 8/28572496 7283/4950376 14221/783360 int[]
5: 601661/24910032 204358/6248200 63154/3887328 334149/14774504 0/0 java.lang.Object[]
6: 141225/21381376 0/0 0/0 0/0 141225/21381376 * ConstMethodKlass
相关推荐
在本篇文章中,我们将分享一个 Full GC 问题排查过程,通过示例代码和实际操作,介绍了如何快速定位 Full GC 问题的原因和解决方案。 问题描述 在我们的服务中,突然出现了频繁的 Full GC 问题,而服务本身没有...
在这个案例中,主要涉及的是线上服务的内存管理与问题排查,特别是针对Java应用程序的内存报警。以下是相关的知识点: 1. **内存报警**:当服务器的内存使用率超过一定阈值时,系统会发送报警,提示可能存在内存...
VisualGC作为JVisualVM的一个重要插件,使得开发者能够直观地查看和分析Java应用程序的垃圾收集情况。本文将详细介绍这两款工具的使用和其背后的原理。 一、JVisualVM简介 JVisualVM是Oracle JDK的一部分,它允许...
性能问题是JVM另一大常见问题,包括但不限于CPU占用率过高、GC频繁、响应时间长等问题。 - **性能监控**:使用JVisualVM、JConsole等工具对JVM进行实时监控,收集CPU、内存、线程等方面的数据。 - **GC日志分析**:...
总结来说,lendengine应用的JVM调优是一个综合性的工程,涉及到日志处理、内存管理、垃圾回收策略、线程池优化等多个方面。通过深入理解JVM的工作原理,针对性地调整相关参数,可以有效解决性能问题,提升服务的稳定...
3. **解决线上GC频繁问题**: 当遇到频繁的垃圾回收时,应首先通过监控工具分析GC日志,查看是否存在不合理的参数配置,如堆大小设置、新生代和老年代的垃圾收集器选择等。同时,检查是否有内存泄漏或异常的大对象...
3. **解决线上GC频繁问题**:这通常涉及到监控、参数调整和问题排查。可以使用JConsole、VisualVM等工具查看GC日志,分析FGC(Full GC)频率。检查JVM参数设置,如堆大小、新生代与老年代的比例、垃圾收集器类型等。...
"Jvm优化的Java - Demo"是一个项目,旨在演示如何调整JVM参数来优化Java应用程序的性能。通过这个项目,我们可以学习到JVM调优的一些核心概念和实践技巧。 首先,JVM参数调整是提高应用程序性能的重要手段。这通常...
- 对象分配:减少短生命周期对象在老年代的分配,避免Full GC频繁触发。 - 泛型使用:避免过度使用泛型,因为泛型信息在编译后会被擦除,可能导致额外的类型检查和装箱操作。 - 数据结构优化:根据实际需求选择...
"练习JVM调优-jvm_demo.zip"是一个压缩包,包含了用于JVM调优实践的示例项目"jvm_demo-master"。通过这个项目,我们可以深入学习和理解JVM的工作原理和调优技术。 1. **JVM结构与工作原理**: - 类加载器:加载、...
最后,JVM的性能监控和调优是一个持续的过程,涉及到许多方面,如内存配置、线程管理、GC策略选择等。开发者应根据具体的应用场景和性能需求,灵活运用各种JVM指令进行调优。 总的来说,掌握JVM的常用指令和工作...
在实际应用中,频繁的Full GC、不合理的内存设置以及内存泄露都是可能导致性能问题的因素,需要通过上述工具进行监控和分析,以便进行有效的内存管理和优化。对于内存排查,可以使用-jmap生成heap dump,然后用MAT...
3. **大对象问题**:FrameworkLogEntry对象异常庞大,可能是由于日志记录过于频繁,每个日志条目都创建了一个大对象,超过了JVM对大对象的处理能力。 4. **JVM配置不当**:JVM的堆内存设置不合理,例如最大堆内存...
- **永久代(Perm Gen space)**:JDK 8之前的版本,存储类元数据,后被元空间替代,原因是防止Full GC频繁触发。 5. **垃圾收集算法**: - **标记-清除(Mark-Sweep)**:标记无用对象并清理,效率低,有碎片...
JVM作为一个抽象层,使得Java程序可以在任何支持JVM的操作系统上运行,无需重新编译。 Java语言的核心特性包括面向对象、自动内存管理(垃圾收集)、强类型、丰富的类库以及简洁的语法。其中,垃圾收集是Java的一大...
6. **线程栈**:每个线程都有一个独立的栈,用于存储方法调用帧。`-Xss`参数可设置每个线程的栈大小,过大可能导致内存浪费,过小则可能引发StackOverflowError。 7. **编译优化**:JVM有即时编译器(JIT),会将...
- **分代**:进一步细分,年轻代又分为Eden区和两个Survivor区,新创建的对象首先放在Eden区,经过一次Minor GC后存活的对象会移到Survivor区,多次存活后进入老年代。 - **性能考虑**:不同的垃圾收集器有不同的...
通过对以上各方面的深入理解和优化,我们可以有效地打造一个高性能、高可用的亿级流量秒杀系统,满足大规模并发场景下的业务需求。在实际操作中,需要根据具体业务特点和资源限制灵活调整优化策略。
1. 根据应用特性调整内存分配,避免频繁GC。 2. 优化对象生命周期,减少短生命周期对象进入老年代。 3. 使用适当的垃圾收集器,平衡吞吐量和停顿时间。 4. 定期进行性能测试,监控系统指标,及时发现问题。 通过...
- Java虚拟机栈:每个线程都有一个独立的栈,用于存储方法调用的状态,包括局部变量、操作数栈和方法返回地址。 - 本地方法栈:服务于Java的本地方法接口,为非Java语言(如C++)编写的native方法服务。 - 堆:...