关于堆外内存的文章JVM——堆外内存详解
关于Java进程内存使用为什么Java进程使用的RAM比Heap Size大
javacv
底层是jni
,主要使用的是堆外内存。
javacv默认使用的堆外内存是两倍或者三倍于maxMemory
。
即便不使用javacv,各个Java进程也会有不等量堆外内存占用,可以使用pmap查看具体使用情况,或者检测使用情况,分析堆外内存是否有溢出风险。
使用javacv可以不限制堆外内存占用,参数可以设置
org.bytedeco.javacpp.noPointerGC=true
或者
-Dorg.bytedeco.javacpp.maxPhysicalBytes=0
-Dorg.bytedeco.javacpp.maxBytes=0
或者设置为一个适当的数量
-Dorg.bytedeco.javacpp.maxPhysicalBytes=8g
-Dorg.bytedeco.javacpp.maxBytes=8g
给javacv分配多少堆外内存?可以通过pmap
监控进程堆外内存使用情况。
pmap -x 2060331
2060331: java -XX:+UseG1GC -Xms300m -Xmx300m -XX:+PrintGC -Dorg.bytedeco.javacpp.maxPhysicalBytes=400m -Dorg.bytedeco.javacpp.maxBytes=400m -Dorg.bytedeco.javacpp.noPointerGC=false -Dorg.bytedeco.javacpp.logger.debug=true -Dorg.bytedeco.javacpp.logger=slf4j -jar opencv-release.jar --spring.profiles.active=test
Address Kbytes RSS Dirty Mode Mapping
0000000000400000 4 0 0 r-x-- java
ffffffffff600000 4 0 0 r-x-- [ anon ]
---------------- ------- ------- -------
total kB 2659000 436508 416156
2060331
进程日志
java.lang.OutOfMemoryError: Cannot allocate new PointerPointer(8): totalBytes = 40, physicalBytes = 416M] with root cause
java.lang.OutOfMemoryError: Physical memory usage is too high: physicalBytes (416M) > maxPhysicalBytes (400M)
可以看出设置与实际使用是一致的。
通过org.bytedeco.javacpp.noPointerGC=true
和-Dorg.bytedeco.javacpp.maxPhysicalBytes=800m -Dorg.bytedeco.javacpp.maxBytes=800m
参数启动不同进程对比运行情况,长时间服务运行,分析出这个进程使用堆外内存稳定在600MB的水平。
云服务器上的进程情况
20171: java -XX:+UseG1GC -Xms512m -Xmx512m -jar socket-1.0.41-eureka.jar --spring.profiles.active=develop
Address Kbytes RSS Dirty Mode Mapping
---------------- ------- ------- -------
total kB 4488964 995640 981756
这个服务堆外内存使用也是接近临近值呀,一不留神就会FullGC
,甚至oom-killer
。