异常提示是直接缓冲区不足,堆外的,没有做最大大小限制,我的程序应该没有内存泄漏
直接缓冲区的 memory 情况
------- used total max usage
direct 183M 183M - 100.00%
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memoryHandler dispatch failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memory
这种异常考虑是怎么产生的?我重启过程序进程,有些不好排查了
我感觉是服务器当时内存不够了导致的?但是内存很大了
服务器内存使用情况
free -h
------- total used free shared buff/cache available
Mem: 251G 118G 54G 1.1G 79G 130G
Swap: 4.0G 0B 4.0G
目前这个情况也不能复现了,应该怎么继续排查?
NIO中Bits类下面,这个预留内存的占用量一直没有降下去导致的,这个为啥没被清理啊?
1
shuson 2023-08-15 12:18:18 +08:00
jvm vm arguments 加上个 -XX:MaxDirectMemorySize=512m
|
3
shuson 2023-08-15 13:21:08 +08:00 1
|
4
zed1018 2023-08-15 13:28:03 +08:00 1
感谢楼上,其实如果有 oss ,我更建议是做一次性 token 让 client 直接传到 oss 里
|
5
Nooooobycat 2023-08-15 13:46:46 +08:00
直接把上传文件的核心代码发上来吧? 说不定 GPT 能帮你 debug 。
|
6
gzk329 OP @Nooooobycat 第一层上传直接用的 Spring 的 MultipartFile , 不是我写的,在这一层就 Direct buffer memory 不够了
|
7
gzk329 OP 这 Spring 的 MultipartFile 是不是有点离谱啊 各种 OOM 用了直接内存区 又不清理
|
8
arloor 2023-08-15 18:59:40 +08:00
看下代码
|
9
xinshoushanglu 2023-08-15 19:33:34 +08:00
前端上传东西不限制大小的么?传大文件 也直接走 表单上传 那不是对后端压力山大,建议走前端上传 oss 的方式
|
10
gzk329 OP 我研究了下好像是因为使用方式的问题,multipartFile.getBytes()这种方式会导致直接内存区使用增加,还不会释放,
multipartFile.transferTo(tempFile)这个方法就不会。 multipartFile.getBytes() 这个方法好像是会拷贝一份 byte[]出来,但是这种不是应该在堆内吗,用完了也就 GC 了,咋会导致直接内存区不断增,一直到溢出啊? // try (OutputStream out = Files.newOutputStream(tempFile.toPath())) { // out.write(multipartFile.getBytes()); // } catch (IOException e) { // e.printStackTrace(); // } |
11
gzk329 OP 定位出一个 jdk 的 bug 了,给 oracle 提了 bug ,多久会有邮件回复啊?
|
12
gzk329 OP 这个问题我后来定位出来了,使用 JDK 8
try-with-resource 机制 自动关闭 Files.newOutputStream 生成的流,流正常关闭,堆外内存释放,但是 java.lang.nio.Bits 中的 reserveMemory ,这个内存占用没有被清理,多次操作之后会 OOM 。 改写为 try-with-resource 机制 自动关闭 FileOutputStream 流,就不会有这个问题。 所以推断是 JDK 的 bug |