一,创建线程池时,可能使用Excutors的四种方式。
newSingleThreadExecutor()和 newFixedThreadPool(int nThreads),内部实现队列为 LinkedBlockingQueue。
LinkedBlockingQueue 是一个由链表实现的有界阻塞队列,容量默认值为 Integer.MAX_VALUE,(也可以自定义容量,建议指定容量大小),
默认大小在添加速度大于删除速度情况下有造成内存溢出的风险,LinkedBlockingQueue 是先进先出的方式存储元素。
newScheduledThreadPool(int corePoolSize)和 newCachedThreadPool()的最大线程数为Integer.MAX_VALUE,同一时刻并发任务多,导致快速创建多个线程,造成内存溢出。
解决方式:使用ExecutorThreadPool自定义线程池的各个参数
二, 堆溢出(java.lang.OutOfMemoryError: Java heap Space)
在对象创建的数量达到最大堆容量限制后就会产生oom;
解决方式:通过参数 -XX:+HeapDumpOnOutOfMemoryError 可让虚拟机出现oom时Dump出当前堆转储快照以便事后分析。
重点确认内存中的对象是否是必要的,也就是要分清楚时内存泄漏还是内存溢出
内存泄漏:通过Dump文件分析,出现异常的进程和类,并准确的定位到出现泄露的代码位置
如果非内存泄漏,那应该检查虚拟机的对参数(Xmx与Xms)与物理机的内存对比看是否可调大。
三,虚拟机栈和本地方法栈溢出
hotspot虚拟机不区分虚拟机栈和本地方法栈,栈容量只有 -Xss参数来设定,关于虚拟机栈和本地方法栈,在Java虚拟机规范中描述了两种异常:
1.StackOverflowError: 线程请求的栈深度大于虚拟机所允许的最大深度时。(递归)
2.OutOfMemoryError: 虚拟机在扩展时无法申请到足够的内存空间。