java进程内存限制
我司所有java服务都是跑在容器里的,但是这些都是受cgroup限制的。但是经常发现有几个服务一直会被重启。虽然一般分配的内存都是heap的1.3到1.5倍。但是还是架不住经常重启。
而观察了一些,发现都是不是heap的gc的引起的。那问题就明显指向到了堆外。
经过参考几位大佬(主要是 qu dongfang)的文章。因为他把堆外内存包含了哪些都说清楚了,但是最后发现还是有漏的。于是把参数进行了如下调整,这个时候整个容器的内存大小改为了1536MB
1 |
|
可结果还是超,直接就被oom了。
qudongfang这位大佬在日志里是这样写的
1 |
|
最后发现还有地方是在堆外里的
- Unsafe.allocateMemory()是一个围绕os::malloc的包装, 这个是直接调用操作系统来申请的内存,根本不受vm里任何内存限制。 那这种问题就无解了。
- spring boot 2.0.5.RELEASE 之前版本的原因。Spring
Boot依赖于finalize机制去释放了堆外内存;但是glibc为了性能考虑,并没有真正把内存归返到操作系统。这个就是为什么我们看到明明有GC,但是你观察进程的RSS使用居然只会网上涨,而从来不会减少的原因。
而以上2点恰恰是这个服务的特征,不过还没有使用大佬的方法去进行验证下。
美团那篇文章居然还有老外翻译了一下,居然还有人在后面评论。然后好多中文的资料都是错误的。
参考:
https://icoding.live/2018/08/25/jvm-gc-intern-swap/
http://www.concurrent.work/docker/java/jvm/gc/pitfalls-about-running-java-inside-container/
https://www.jianshu.com/p/e1503204a059
https://www.jianshu.com/p/b6dedd95e9d9
http://cn.voidcc.com/question/p-fitcryus-hr.html
https://www.cayun.me/java/Java%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E4%B8%8E%E9%87%8A%E6%94%BE%E5%8E%9F%E7%90%86/
https://tech.meituan.com/2019/01/03/spring-boot-native-memory-leak.html