前言
在日常的Android开发中,每个开发者或多或少都会遇到过OutOfMemoryError这样崩溃信息。如果工程稍微大一些,在monkey测试的崩溃日志也是比较常见的一种。如下是比较常见的一些报错信息:
Android:java.lang.OutOfMemoryError: Failed to allocate a 1340012 byte allocation with 72503 free bytes and 70KB until OOM
OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)
COMPILETODALVIK : UNEXPECTED TOP-LEVEL error :
java.lang.OutOfMemoryError: Java heap space
...
java.lang.StackOverflowError
...
相对于StackOverflowError而言OutOfMemoryError则是比较常见的一种内存异常。在《深入理解Java虚拟机》一书中有对这两种异常信息的简单描述。
如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出StackOverflowError;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可以动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError。
StackOverflowError不常见,主要在渲染复杂布局或者动态缓存数据到数据库时比较常见。而OutOfMemoryError只要内存泄漏多了就有可能导致内存溢出。
内存泄漏与内存溢出
内存泄漏 Memeory Leak程序在向系统申请分配内存空间后(new),在使用完毕后未释放。结果导致一直占据该内存单元,我们和程序都无法再使用该内存单元,直到程序结束,这是内存泄露。
内存溢出 Out Of Memory是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如内存只能分配一个int类型,我却要塞给他一个long类型,系统就出现oom。又比如一车最多能坐5个人,你却非要塞下10个,车就挤爆了。
内存泄漏的堆积最终会导致内存溢出。从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。
为什么会产生内存泄漏
为了判断Java中是否有内存泄漏,首先我们必须了解Java是如何管理内存的。Java的内存管理可以简单理解为对象的分配和释放。在Java中内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)自动完成的。程序员不需要自己调用方法释放内存,但它只能回收无用且不被其它对象引用的那些对象占用的空间。
Java内存回收机制就是从程序的GC root(静态对象以及堆内存对象等)开始检查引用链,当遍历一遍之后得到上述无法回收的对象以及它们