JVM的OOM分为多种情况,下面会针对java.lang.OutOfMemoryError: Java heap space这种情况讲解一下发生的原因与解决方案。在JAVA应用启动时,会限制应用的使用空间。也就说,任何一个JAVA应用,都只能使用有限的内存空间。
好在 Android 系统维护人员也意识到了这种问题,从 Android O 系统开始,对 Java 内存管理策略进行了调整,重点包括实例化 Bitmap 对象时,Bitmap 源数据的内存不再通过虚拟机申请,而是直接在 Native 层申请和管理,因此这部分内存不会纳入虚拟机 Heap 内存统计,以此来减少 LargeSpace 的占用,进而间接增加了其他内存空间的实际使用范围,如下示意图:
随着平台业务的不断发展,平台曲库数据的不断增加,系统偶尔出现内存溢出的情况。内存溢出相比其它异常而言,通常比较隐晦,一般是伴随着时间慢慢积累而产生的,因此不能仅根据异常产生处来简单定位问题,而要找到问题的根源。所以,有必要知道如何排查系统的内存溢出。
再通过jstack命令查看该线程:jstack -l 16327 | grep -20 3fca。可以看到OOMObejct对象创建了400多万个实例,明显异常,我们通过搜索代码OOMObject对象的usages,发现该代码在:这里有一个死循环,至此问题排查到,修改后重新上线。
查看ES的jvm,如下图:O:Old space utilization as a percentage of the space's current capacity 。O最高达到79,就往下降,原来为存储类型为“mmapfs”,O很容易就飙到100。
面试官:你这个太抽象了,能不能具体点?首先,我们铺垫了什么是 OOM,以及 OOM 发生的场景,包括内存溢出、内存泄漏,从而得出了这个问题:当 Java 线程在处理请求时,抛出了 OOM 异常,整个进程还能处理请求吗?
首先说一下,本人在开发中遇到的OOM异常基本也是通过看log日志去定位的(很多OOM异常是因为出现死循环或者查询返回的数据量多大,没有分页等等,通过异常日志我们确实能很快定位,但这不是正确的姿势。),只是碰巧刚好日志打印的异常栈信息就是对应的代码问题。