当前位置:首页 > 内存 > 正文

java排查内存高的原因(Java占用内存一直升高)

  • 内存
  • 2024-08-23 04:32:51
  • 7120

一、一次Java内存占用高的排查案例,解释了我对内存问题的所有疑问问题:
7月25日,JVM堆内存减少至总内存的60%(即9.6GB)。与其他服务相比,尽管配置相同,该服务的内存使用率达到了85%,高于平均水平70%-79%。
排查过程:
1.
检查堆内存和垃圾回收:Java堆内存使用正常,没有发现明显异常。
2.
非堆内存详细信息:如果您监控数据,您将看到非堆内存使用情况也在正常范围内。arthas工具分析显示,所有虚拟内存段在pmap中都有对应的段,但64M内存块的数量异常大,这可能是问题所在。
3.
内存泄漏的识别:分析发现新增的内存段包含与内部开发的消息队列相关的响应格式数据。这很可能是由主题新迁移的消息引起的。
4.
代码审查:发送消息的http接口代码中发现未关闭的流对象导致内存泄漏。特别是,GZIPInputStream直接分配本机内存中。。
5.
其他故障排除方法:通过NMT本机内存跟踪和glibc内存分配器缓存的内存检查,您可以验证内存使用情况是否来自代码而不完全来自缓存确保有。逻辑问题。
6.
内存泄漏检测工具:使用tcmalloc检测Inflater对象中的内存泄漏。此内存泄漏是由未关闭的流对象引起的JNI调用成的。
内存增长分析:
Inflater对象内存问题可以通过GC回收来解决,但如果不修复,内存可能会继续增长。在我们的实验中,强制FullGC后,JVM返回了一些内存,但进程的rss并没有明显下降,因为glibc缓存了内存。
优化实践:
问题出在InputStream流对象的管理上,所以一定要在finally块中调用close方法来释放资源。同时,GZIPInputStream和Inflater很容易出现内存泄漏,因此在检查代码时应该特别小心。
内存问答:
-
Xmx设置与实际内存使用情况:了解JVM内存结构表明-Xmx值小于内存的65%就变成了出来你需要它。实现容器内存的高效使用。
-
顶部的VIRT和RES:VIRT是虚拟内存,RES是真实内存。JVM之所以有较大的VIRT,是由于glibc内存管理机制所致。
-
内存使用量增加:服务启动初期,内存使用量增加是正常现象。这可能与您的堆内存分配策略有关,可以通过以下方式改进:AlwaysPreTouch参数。
总结:
经过对内存使用问题的彻底排查,我们发现内存使用异常,主要是由于未关闭的流对象以及某些内存管理机制造成的,导致这种情况的原因已经找到。通过调整代码并了解内存管理原理,您解决了问题并学习了内存监控和优化的最佳实践。
二、java内存溢出的问题如何排查众所周知,在Java程序中,内存溢出是一个常见的错误,下面我们就从基本的分析开始吧!
内存溢出是由于未引用的对象(垃圾)过多导致JVM无法及时回收它们而导致的内存溢出。如果出现这种现象,可以进行代码调试:
1)在类的属性中使用静态修改时,类中是否使用了过多的publicstaitcStudents等静态修改以及应用中的引用变量,最好;仅使用基本类型或字符串。例如publicstaticinti=0;//publicstaticStringstr;
2)应用程序是否使用大量递归或无限递归(递归使用许多新对象)
3)应用程序是否使用许多循环或无限循环(循环中使用了大量新创建的对象)
4)检查应用程序是否使用该方法查询数据库中的所有记录。即一次查询全部的方法如果数据量超过10万条可能会导致内存溢出,因此查询时应采用“分页查询”。
5)检查是否存在存储对象引用而不是对象的数组、列表或映射,因为这些引用会阻止相应的对象被释放。将大量存储在内存中。
6)检是否使用了“非文字字符串+”操作。因为String类的内容是不可变的,所以每次执行“+”都会生成新的对象。如果太多,就会new出太多的String对象,导致JVM不能及时回收,造成内存占用。漂浮。
如Strings1="我的名字";
Strings2="is";
Strings3="xuwei";
Stringstr=s1+s2+s3+.....;这样很容易造成内存溢出
但是Stringstr="Myname"+"is"+"xuwei"+"nice"+"to"+"hit";//但是这样不会造成内存溢出。因为这是一个“文字字符串”,所以“+”在编译期间运行。不会按照JVM执行。
使用String、StringBuffer和StringBuilder时,如果有“+”的字符串字面量,应该使用String以获得更好的性能,如果有“+”的String类,如果不考虑线程安全,应该使用String通过选择StringBuilder来使用以获得更好的性能。
一旦知道原因,解决办法就很简单了。