哪些地方会有OOM
jvm内存模型
线程私有
程序计数器:当前线程执行的字节码指示器
虚拟机栈:java方法执行的内存模型,每个方法的执行,就是栈帧进栈和出栈的操作过程
本地方法栈:native方法的运行提供内存环境
线程共享
方法区:用于存储jvm的类加载信息、常量、静态变量,即时编译器编译后的代码等,又称永久代
常量池:常量信息如:符号引用、字面量
堆:对象内存分配的地方,垃圾回收的主要区域
直接内存:并不是JVM运行时数据区的一部分, 可直接访问的内存,
除了程序计数器,其他地方都有可能OOM
为什么会有OOM
原因
内存分配少了:虚拟机本身分配的内存太小了
内存溢出:申请的内存超出了jvm总内存的大小
应用用的多了:应用用的内存多了,并且没有释放
内存泄漏:申请使用完后没有释放,导致虚拟机不能再次使用
OOM类型
java.lang.OutOfMemoryError: Java heap space
堆内存分配少了:-Xms -Xmx
使用不当:通过监控软件查找
java.lang.OutOfMemoryError: PermGen space
大量class或jsp页面,类的信息会存在这个里面:-XX:PermSize -XX:MaxPermSize
大量CGLIB反射动态代理,大量类的信息
过量常量和字符串
java.lang.StackOverflowError
程序中存在死循环
栈内存设置太小:-Xss
如何定位OOM
设置参数:-XX:+HeapDumpOnOutOfMemoryError 设定当发生OOM时自动dump出堆信息
dump命令工具
jps:定位进程PID
jmap:jmap -dump:format=b,file=heap.bin PID
jmap -dump:live,file=a.log pid
工具
jconsole
jvisovm
分析工具
jhat
jhat -J-Xmx512M a1.log
http://localhost:7000
(1)查询长度大于100的字符串
select s from java.lang.String s where s.count > 100
(2)查询长度大于256的数组
select a from [I a where a.length > 256
(3)显示匹配某一正则表达式的字符串
select a.value.toString() from java.lang.String s where /java/(s.value.toString())
(4)显示所有文件对象的文件路径
select file.path.value.toString() from java.io.File file
(5)显示所有ClassLoader的类名
select classof(cl).name from instanceof java.lang.ClassLoader cl
(6)通过引用查询对象
select o from instanceof 0xd404d404 o
mat
如何预防OOM
增加jvm内存
配置XX:+HeapDumpOnOutOfMemoryError
防止死循环
定位问题
防止动态代理加载类过多
防止内存使用不释放