Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-03-14:哪些情况下会导致oom问题? #5

Open
Moosphan opened this issue Mar 14, 2019 · 25 comments
Open

2019-03-14:哪些情况下会导致oom问题? #5

Moosphan opened this issue Mar 14, 2019 · 25 comments

Comments

@Moosphan
Copy link
Owner

No description provided.

@ADrunkenLiBai
Copy link

该释放回收的资源没有释放掉,字节流没有关掉,activity被持有得不到释放,大图加载,等等等等

@Ssuiyingsen
Copy link

举个栗子
1.例如handler 在界面销毁的时候消息还未发送
2.file没有关流
3.查询到结果还没有停止
4.内部类持有外部类引用得不到释放
5.不用的对象最好null 让GC回收一下
6.图片资源什么的最好加一个软引用

@Moosphan
Copy link
Owner Author

@wardenlzr 使用 StringBuilder 代替 String 来实现大量字符串的拼接,之前回答的角度有问题

@jamsgithub
Copy link

jamsgithub commented Mar 27, 2019

StringBuilder ?? 能详解下不?
因为当我们创建一个String的变量后,当我们需要修改这个变量的值时,因为String是不可变对象,所以会新创建一个同名的变量String对象,并将以前的变量回收,而StringBuilder,在我们修改其值时,实际是对其对象本身操作,不涉及对象的新建和引用指向问题。如果我们不涉及到线程安全问题,我们可以使用StringBuilder(线程不安全的),相反可以使用StringBuffer。详情可以参考这个:https://www.cnblogs.com/goody9807/p/6516374.html

@Alex-Cin
Copy link

Alex-Cin commented Mar 28, 2019

该释放回收的资源没有释放掉,字节流没有关掉,activity被持有得不到释放,大图加载,等等等等

@ADrunkenLiBai
你这是内存泄漏, 并不是OOM;大图加载,算是OOM;

@Alex-Cin
Copy link

Alex-Cin commented Mar 28, 2019

楼上好多在混淆 内存泄漏和内存溢出啊;
OOM常见就是,申请内存资源,语义上是正确的,但是JVM无法承载,出现不可原谅的错误, api叫Error;
大家顺便看另一个面试题 Error 和 Exception 的区别;
例如 for 100K 个 string, 或者 thread 或者其他对象, 或者加载100MB的png等等;
或者栈内存溢出,死循环调用方法等,但是方法栈溢出,也不能叫做OOM,可以算作内存溢出;

@jamsgithub
Copy link

楼上好多在混淆 内存泄漏和内存溢出啊;
OOM常见就是,申请内存资源,语义上是正确的,但是JVM无法承载,出现不可原谅的错误, api叫Error;
大家顺便看另一个面试题 Error 和 Exception 的区别;
例如 for 100K 个 string, 或者 thread 或者其他对象, 或者加载100MB的png等等;
或者栈内存溢出,死循环调用方法等,但是方法栈溢出,也不能叫做OOM,可以算作内存溢出;

但是过多的内存泄漏容易导致内存溢出出现的频率。

@Alex-Cin
Copy link

Alex-Cin commented Apr 1, 2019

那就回答, 过多的泄漏也会导致溢出, 而不是回答什么情况会导致泄漏, 然后围绕着泄漏回答好多;
如果面试官让你解释内存泄漏, 再继续回答;
我的建议, 是这样的, 面试时间本就有限;
@jamsgithub

@darrenjh
Copy link

darrenjh commented Apr 8, 2019

第6点,StringBuilder是什么意思?难道我用多了StringBuffer会造成内存溢出吗?

@MrSimpleX
Copy link

第6点,StringBuilder是什么意思?难道我用多了StringBuffer会造成内存溢出吗?

直接使用String会创建销毁多个实例,对性能有影响,StringBuffer只会一直操作同一个StringBuffer对象,就优化了内存使用。另外new的对象的内存超过了虚拟机的最大内存并且GC不掉就会内存溢出吧

@liupengfei666
Copy link

个人觉得没毛病,内存溢出跟内存泄漏还是有区别的。过多的内存泄漏会导致内存溢出,但是内存泄漏不一定会导致内存溢出,还是要严谨一点。

@risechen
Copy link

risechen commented May 7, 2019

1、根据java的内存模型会出现内存溢出的内存有堆内存、方法区内存、虚拟机栈内存、native方法区内存;
2、一般说的OOM基本都是针对堆内存;
3、对于堆内存溢出主的根本原因有两种
(1)app进程内存达到上限
(2)手机可用内存不足,这种情况并不是我们app消耗了很多内存,而是整个手机内存不足
4、而我们需要解决的主要是app的内存达到上限
5、对于app内存达到上限只有两种情况
(1)申请内存的速度超出gc释放内存的速度
(2)内存出现泄漏,gc无法回收泄漏的内存,导致可用内存越来越少
6、对于申请内存速度超出gc释放内存的速度主要有2种情况
(1)往内存中加载超大文件
(2)循环创建大量对象
7、一般申请内存的速度超出gc释放内存基本不会出现,内存泄漏才是出现问题的关键所在
8、内存泄漏常见场景
(1)资源对象没关闭造成的内存泄漏(如: Cursor、File等)
(2)全局集合类强引用没清理造成的内存泄漏(特别是 static 修饰的集合)
(3)接收器、监听器注册没取消造成的内存泄漏,如广播,eventsbus
(4)Activity 的 Context 造成的泄漏,可以使用 ApplicationContext
(5)单例中的static成员间接或直接持有了activity的引用
(6)非静态内部类持有父类的引用,如非静态handler持有activity的引用
9、怎么对内存进行优化呢
三个方向
(1)为应用申请更大内存,把manifest上的largdgeheap设置为true
(2)减少内存的使用
①使用优化后的集合对象,比如SpaseArray;
②使用微信的mmkv替代sharedpreference;
③对于经常打log的地方使用StringBuilder来组拼,替代String拼接
④统一带有缓存的基础库,特别是图片库,如果用了两套不一样的图片加载库就会出现2个图片各自维护一套图片缓存
⑤给ImageView设置合适尺寸的图片,列表页显示缩略图,查看大图显示原图
⑥优化业务架构设计,比如省市区数据分批加载,需要加载省就加载省,需要加载市就加载失去,避免一下子加载所有数据
(3)避免内存泄漏
编码规范上:
①资源对象用完一定要关闭,最好加finally
②静态集合对象用完要清理
③接收器、监听器使用时候注册和取消成对出现
④context使用注意生命周期,如果是静态类引用直接用ApplicationContext
⑤使用静态内部类
⑥结合业务场景,设置软引用,弱引用,确保对象可以在合适的时机回收
建设内存监控体系:
线下监控:
①使用ArtHook检测图片尺寸是否超出imageview自身宽高的2倍
②编码阶段Memery Profile看app的内存使用情况,是否存在内存抖动,内存泄漏,结合Mat分析内存泄漏
线上监控:
①上报app使用期间待机内存、重点模块内存、OOM率
②上报整体及重点模块的GC次数,GC时间
③使用LeakCannery自动化内存泄漏分析
10、真的出现低内存,设置一个兜底策略
低内存状态回调,根据不同的内存等级做一些事情,比如在最严重的等级清空所有的bitmap,关掉所有界面,直接强制把app跳转到主界面,相当于app重新启动了一次一样,这样就避免了系统Kill应用进程,与其让系统kill进程还不如浪费一些用户体验,自己主动回收内存

@RedDargon
Copy link

OOM 即 out of memory 内存溢出 。
每个进程能够支配的内存是有限的,所以资源要记得使用完及时释放,如果未释放,就有可能造成内存泄漏,内存泄漏达到一定程度 手机就会造成内存溢出。
业务场景上面的话多为加载过大的图片,或者代码问题造成的各种内存泄漏累积出现的内存溢出 。

Repository owner deleted a comment from Ssuiyingsen Jun 4, 2019
@ChenLeizheng
Copy link

线程开多了
java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again

@KollerWithDoris
Copy link

线程开多了
java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again

我记得一个线程要占大约2M的内存大小。所以开多了肯定会有内存问题。

@ZHANGfeng-james
Copy link

我遇到的一般是:线程创建过多和加载较大的资源文件。

确实应该区分:内存溢出和内存泄漏。

@siren4
Copy link

siren4 commented Aug 12, 2019

首先明确一点,内存泄漏和内存溢出是不同的,但是过多的内存泄漏会导致内存溢出。
内存溢出的根本原因:
1.应用申请内存的速度超过了gc内存回收的速度。
2.应用申请的内存大小超过了手机的可用内存。

常见的内存溢出的原因:
1.加载超大的图片、文件
2.创建大量的对象

内存优化的方法:
1.申请更大的内存,比如多进程、设置manifest中的largeHeap=true等。
2.减少内存使用
①使用优化后的集合对象,分场景使用SpaseArray和HashMap;
②使用微信的mmkv替代sharedpreference;
③使用StringBuilder替代String拼接
④统一带有缓存的基础库,特别是图片库,如果用了两套不一样的图片加载库就会出现2个图片各自维护一套图片缓存
⑤给ImageView设置合适尺寸的图片,列表页显示缩略图,查看大图显示原图
⑥优化业务架构设计,比如省市区数据分批加载,需要加载省就加载省,需要加载市就加载失去,避免一下子加载所有数据
3.避免内存泄漏

@wangxuyang518
Copy link

1.内存泄露
2.写代码在异常中再次重启,陷入无限循环会出现oom
3.资源文件没关闭,例如contentresolver
4.bitmap 没有及时回收。可以减少argb色彩模式占用的大小,尽可能减少bitmap消耗的内存
5android tv 本身内存较少,加载过多的摄像头视频,也会oom

@nealkafuly
Copy link

这位同学,单例模式不会照成内存泄漏,Context引用没有及时释放而已,根本原因不是单例模式。
解决方案:Util.release()即可

@nealkafuly
Copy link

image

@Mrsunbw
Copy link

Mrsunbw commented Nov 25, 2019

1、过多的内存泄漏
2、加载大图
3、创建大量线程

@JesusYoung
Copy link

线程池使用不合理,例如使用FixedThreadPool和SingleThreadPool时,由于这两个线程池的任务队列是无界的LinkedBlockingQueue,所以无限制的添加新任务,当任务过多时会导致OOM发生,或者使用CachedThreadPool时,最大线程数没有限制,创建过多线程,导致OOM

@MoJieBlog
Copy link
Collaborator

内存溢出(oom)说白了就是应用要申请的内存大于手机对该应用的限制。因此所有导致内存增长的操作都是有可能导致内存溢出的。之所以没有看到内存只增不减,是因为JVM的自动垃圾回收机制。所以上面说的导致oom的情况,只是某些特定场景。并不是说加载小图就不会oom,也不是说创建一个线程就不会oom,也不是说内存泄漏就一定会oom...举个例子:

比如:假如你有一个10立方米的水桶,你一次倒入1立方米的水,前10次都不会溢出,但是第11次就要开始往外取1立方水(相当于内存回收)才能继续倒水,不然就会溢出水(oom)。

@mlinqirong
Copy link

1过多的内存泄漏会导致内存溢出
2,加载大的图片
3,创建过多的线程

@yline
Copy link

yline commented Sep 1, 2023

OOM,内存溢出。

从应用的角度来看,当内存超过系统给当前进程允许的最大内存,或者,系统的内存不足,无法分配新的内存时;就会触发OOM。
从编码的场景来看,就是内存不够了,因此,只要申请了内存的操作,都有可能会触发OOM。

这也是为啥,OOM上报的堆栈,往往都是无用的,大概率并不能直接用于解决OOM的Crash。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests