同事写了一条 SQL,把 MyBatis 都干翻了
前言
OutOfMemoryError出现的原因
OutOfMemoryError
出现的原因,无非就是两类堆内存空间不足、元空间不足。-
堆内存空间不足:意味着程序存在一直有引用的对象(强引用),主要对象在引用的状态就无法被GC回收,撑爆了-Xmx堆拓展的最大值,内存不足自然就会触发堆内存溢出。 -
元空间:Java 8 引入了元空间概念,代替了之前堆的永久代,由于元空间属于堆外内存,不需要有对象引用,通过指针的方式表示类和元数据,之所以引用元空间就是一种 JDK 的升级优化,避免了永久代的内存溢出。
常见堆内存溢出的几种情况
-
查询数据库返回的数据量过大,加载到内存中导致内存溢出; -
代码中出现死循环情况,导致大对象一直被引用不能被 GC 回收; -
资源链接池、io 流在使用完没有进行手动释放; -
静态集合类里面存在引用对象,始终存在引用关系,没有进行清除;
现象分析

Mybatis源码分析
DynamicContext
类源码查看,DynamicContext 又一个 ContextMap 类型的参数bindings,继承了 HashMap 相当于一个Map集合,接着看这个类中的 getBindings 方法,看到了 ForEachSqlNode 这类调用了 getBindings 方法,简单的说就是 ForEachSqlNode 通过 getBindings 方法,将 SQL 参数和参数的占位符统一 put 到 ContextMap 这个集合里面,主要是这里面的参数和占位符无法被 GC 回收,并发查询量多的情况下就会导致 OOM。


情景复现
-Xmx256m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError



总结
微信赞赏
支付宝扫码领红包
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。侵权投诉:375170667@qq.com