今天简单复习了JVM的内存组成,以及工作中常见的内存泄露原因,以及内存分析
1.首先说下JVM的内存组成,按照我的理解看来,可以简化成三个比较常接触的内存区域,方法区,堆,栈。
那么比如我们static修饰的常量,方法,类名等是存在我们的方法区中。我们通过new方法创建的对象都是存在我们的堆内存中,那么引用我们这些对象的实例都是存在我们的栈中。
2.GC
JAVA的GC操作的触发我们的无法在代码中控制,这部分我们主要说一下堆内存的垃圾回收,堆内存占用空间最大,也是我们内存泄露问题产生的地方,我们可以把它分为两部分:年轻区域,年老区。
年轻区又可以分为三部分Eden和两个Survivor,我们新创建的对象一般都是放在我们的Eden区域中,但是这个区域满了也可以存放在我们的Survivor中,在这里我们的流程简单来说就是“标记--清除--复制”算法,标记我们要删除的,清除掉它们,复制到从Eden复制到Survivor区或者从一个Survivor区复制到另一个Survivor区,总会有一个Survivor是空的。判断是否需要被清除的条件就是我们的内存中的对象是否还被引用,如果没有,就会被标记为可回收。反复经过上面的流程若干次,还没被回收的对象,就会被移动到我们的年老区,在我的理解力,年老区和年轻区的区别就是年老区进行回收的频率更低,提升我们的运行效率。
3.常见的引起内存泄露,内存溢出问题的原因以及解决
1.减少Static关键字的过度频繁的使用
2.Hnadler,Thread等长生命周期的非静态内部类的不合理使用。这里我们可以使用定义为静态内部类,如果需要的话可以在我们Activity的onDestory生命周期中停止我们callBack中的操作。
3.数据库,流等操作没有关闭。
4.Bitmap图片过大,可以根据效果改变图片的质量。
5.监听器,广播未注销
6.ListView之类的控件未作好回收
7.字符拼接尽量使用StringBuffer,StringBuilder
4.内存分析工具
我在工作中使用过的有两种
1.AndroidStudio上的Montior,这个东西使用简单,但是只能看我们应用内存的总体情况。
2.eclipse上的MAT中的OQL工具,使用类似于SQL的语句,可以查询我们目标应用,甚至目标类的内存状况,举个例子简单来说,我们的一个Activity反复启动,结束,如果在查询结果中存在多个对象,就可以确认这个Activity有被引用的状况,就可以分析这个Activity中的代码。