文章目录
- 版权声明
- 诊断和解决问题 - 两种方案
- 在线定位问题步骤
- 在线定位问题 – btrace
- 总结
- 内存溢出&内存泄漏
- 内存溢出原因
- 解决内存泄漏方法
版权声明
- 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明,所有版权属于黑马程序员或相关权利人所有。本博客的目的仅为个人学习和交流之用,并非商业用途。
- 我在整理学习笔记的过程中尽力确保准确性,但无法保证内容的完整性和时效性。本博客的内容可能会随着时间的推移而过时或需要更新。
- 若您是黑马程序员或相关权利人,如有任何侵犯版权的地方,请您及时联系我,我将立即予以删除或进行必要的修改。
- 对于其他读者,请在阅读本博客内容时保持遵守相关法律法规和道德准则,谨慎参考,并自行承担因此产生的风险和责任。
- 本博客中的部分观点和意见仅代表我个人,不代表黑马程序员的立场。
诊断和解决问题 - 两种方案
在线定位问题步骤
- 使用jmap -histo:live 进程ID > 文件名 命令将内存中存活对象以直方图的形式保存到文件中,这个过程会影响用户的时间,但是时间比较短暂。
- 分析内存占用最多的对象,一般这些对象就是造成内存泄漏的原因。
- 使用arthas的stack命令,追踪对象创建的方法被调用的调用路径,找到对象创建的根源。也可以使用btrace工具编写脚本追踪方法执行的过程。
在线定位问题 – btrace
- BTrace 是一个在Java 平台上执行的追踪工具,可以有效地用于线上运行系统的方法追踪,具有侵入性小、对性能的影响微乎其微等特点。项目中可以使用btrace工具,打印出方法被调用的栈信息。
使用方法:
- 下载btrace工具官方地址
- 在项目中引入jar包,编写btrace脚本,通常是一个java文件
<dependency><groupId>org.openjdk.btrace</groupId><artifactId>btrace-agent</artifactId><version>${btrace.version}</version><scope>system</scope><systemPath>xxx\btrace-v2.x.x-bin\libs\btrace-agent.jar</systemPath></dependency><dependency><groupId>org.openjdk.btrace</groupId><artifactId>btrace-boot</artifactId><version>${btrace.version}</version><scope>system</scope><systemPath>xxx\btrace-v2.x.x-bin\libs\btrace-boot.jar</systemPath></dependency><dependency><groupId>org.openjdk.btrace</groupId><artifactId>btrace-client</artifactId><version>${btrace.version}</version><scope>system</scope><systemPath>xxx\btrace-v2.x.x-bin\libs\btrace-client.jar</systemPath></dependency>
@BTrace
public class TracingUserEntity {@OnMethod(clazz="com.itheima.jvmoptimize.entity.UserEntity",method="/.*/")public static void traceExecute(){jstack();}
}
- 将btrace工具和脚本上传到服务器,配置环境变量,在服务器上运行
btrace 进程ID 脚本文件名
vim /etc/profileBTRACE_HOME=/usr/local/jvm/btrace-v2.2.4-bin
PATH=$PATH:$BTRACE_HOME/bin
export PATH BTRACE_HOME
- 观察执行结果
总结
内存溢出&内存泄漏
- 内存泄漏(memory leak):在Java中如果不再使用一个对象,但是该对象依然在GC ROOT的引用链上,这个对象就不会被垃圾回收器回收,这种情况就称之为内存泄漏。
- 内存溢出指的是内存的使用量超过了Java虚拟机可以分配的上限,最终产生了内存溢出OutOfMemory的错误
内存溢出原因
- 持续的内存泄漏:内存泄漏持续发生,不可被回收同时不再使用的内存越来越多,就像滚雪球雪球越滚越大,最终内存被消耗完无法分配更多的内存取使用,导致内存溢出。
- 并发请求问题:用户通过发送请求向Java应用获取数据,正常情况下Java应用将数据返回之后,这部分数据就可以在内存中被释放掉。但是由于用户的并发请求量有可能很大,同时处理数据的时间很长,导致大量的数据存在于内存中,最终超过了内存的上限,导致内存溢出
解决内存泄漏方法
- 发现问题,通过监控工具尽可能尽早地发现内存慢慢变大的现象
- 诊断原因,通过分析内存快照或者在线分析方法调用过程,诊断问题产生的根源,定位到出现问题的源代码
- 修复源代码中的问题,如代码bug、技术方案不合理、业务设计不合理等等
- 在测试环境验证问题是否已经解决,最后发布上线