本文首发掘金:Thread也会OOM吗?
作者:究极逮虾户
OOM其实是一个比较常见的异常了,但是不知道各位老哥有没有见过这个异常。
java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
at java.lang.Thread.nativeCreate(Thread.java)
at java.lang.Thread.start(Thread.java:1076)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1338)
...
由于国内手机厂商的奇奇怪怪的优化,特别是华为,其对于线程的构建有特别严苛的要求,当进程内总线程数量达到一定的量级的情况下就会发生线程OOM问题。
这个问题其实有人专门做过分析,我这个人还是不喜欢直接复制别人的文章,但是读书人嘛,借书怎么能叫偷呢。不可思议的OOM
在Android7.0及以上的华为手机(EmotionUI_5.0及以上)的手机产生OOM,这些手机的线程数限制都很小(应该是华为rom特意修改的limits),每个进程只允许最大同时开500个线程,因此很容易复现了。
for (i in 0 until 3000) {
Thread {
while (true) {
Thread.sleep(1000)
}
}.start()
}
这个是作者做的一个实验,当华为手机的线程创建超过500的时候就会发生崩溃的问题了。但是我自己写了个demo,发现也不是所有的华为手机都这样,我用NOVA7测试出来的结果大概是3000个线程才会出现崩溃的问题。
线上真的会有超过500个线程的情况出现吗?
如何查看当前线程数量?
Android Profiler 工具非常强大,里面就有当前进程启动的线程数量,以及其cpu调度情况的。
图上可以看出来THREADS
后面的就是当前的线程使用数量。一个只含有少量代码的安卓项目执行的时候其实也有大概30条左右的线程存在,而OKHttp,Glide,第三方框架,Socket以及启动任务栈等等第三方框架接入后,线程数量更是会出现一个井喷式增长。
线上问题原因分析?
我观察了下我们的项目的线程使用情况,发现当项目完成简单的初始化之后就会构建出大概300条左右的线程,其实还是比较感人的。而线上的使用情况很复杂,而且报错日志上的错误并不是oom的真实原因,而是压死骆驼的最后一根稻草。
我其实在上家公司的时候就发生过这个问题,当时我们跟踪源代码,发现在使用rxjava的Schedulers.io()
导致的这个问题。
static final class CachedWorkerPool implements Runnable {
private final long ke