4g内存条价格问题

电脑内存故障分析及解决大全 - 中华考试网()
&&当前位置: >
> 文章内容
电脑内存故障分析及解决大全 &&【
】&&[ 日 ]
第一节:通俗易懂:女孩子都能搞定的故障
  “点不亮,还是点不亮。报警,内存报警。”这是小编在上个月给MM修电脑时遇到的问题。由于内存条直接与CPU和外部存贮器交换数据,其使用频率相当高,再加上内存条是超大规模集成电路,其内部的晶体管有一个或少数几个损坏就可能影响计算机的稳定工作,同时表现出的故障现象也不尽相同,所以给我们的维修工作带来一定的难度。下面小编为大家整理出内存出现的故障,并一一排除。从简单到深入,让大家从不懂到懂,从懂再到会。
  在所有内存故障中,最简单,遇到最多的就属于内存报警啦。如两天的新机器会出现内存报警;使用一年的机器也会出现内存报警;天气突然降温的时候会出现内存报警;夏天长时间阴雨的时候也会出现内存报警;总之一句话,内存报警问题在计算机故障现象中出现频率最多,同时最容易解决的,拆开机箱,把内存拔出来,再插一下就好了。严重一点的需要把机箱内的灰尘清除干净,或者换个内存插槽试一试。相对于其他计算机硬件故障,内存报警可以说是最简单的硬件故障了,对电脑不太了解的女孩子来说都能轻松搞定。
  下面我们就来分析一下,为什么会现出内存报警,出现内存存报警后,如何解决此类问题?
  1 、内存插槽变形
  这种故障不是很常见,一般见于主板有形变,内存插槽有损坏,裂缝等现象,当我们把内存插入内存插槽时就会出现部分接触不良的情况,当主机加电开机自检时就不能通过,就会出现连续的短“嘀”声,也就是大家常说的“内存报警”。
  解决方法:内存插槽变形的现象我们可以在内存插好后通过使用尼龙扎带紧固,再辅以打胶的方法来解决此类问题。&
&DDR2主板内存插槽&
  注意:在拔插内存的过程中我们一定要注意内存的方向,虽然内存条和内存插槽有防呆设计,但是还有很多人仍然把内存插反,造成内存条和内存插槽个别引脚烧熔的情况,这时只能放弃使用损坏的内存插槽。对于引脚烧熔的内存条,我们可以仔细检查一下,如果只是77和85接地端烧熔,也或许是其他内存条的接地端,即使把金手指烧得脱落了,这样的内存条因是接地端在反插时把电源正与地短路了,才造成打火烧毁内存条的金手指和内存插槽的引脚,而内存芯片却没有受到任何损伤,所以这样的内存条我们只要把其插在正常的内存插槽上就可以正常使用。
&DDR内存插槽
  有时我们还要注意内存插槽中是否有其他异物,因为如果有其他异物在内存插槽里,当插入内存时内存就不能插到底,内存无法安装到位,当然就会出现开机报警现象。当我们多次拔插内存仍不能解决问题时,最好仔细检查一下内存插槽是否变形,是否有引脚变形或损坏,脱落,插槽里是否有异物等情况,这样做对我们排除故障很有帮助。
  2、内存金手指氧化
  这种情况最容易出现,一般见于使用半年或一年以上的机器。当天气潮湿或天气温度变化较大时,就会出现昨天机器工作还好好的,可第二天早晨开机时即发现无法正常开机,显示器黑屏,只听得机内“嘀嘀“直响。
  解决方法:只要拆开机箱把内存条重插一下就可以。
  注意:如果这种故障每个月都发生一次或者一个星期或半个月就要出现一次,那就要考虑是不属于内存条与主板兼容性不好的问题了,也就是下面要说的第3种类型的问题。
  预防的方法:
  (1).采用第1种问题中所说的紧固方法解决;
  (2).再就是安装和检修时,一定不能用手直接接触内存插槽的金手指,因为我们手上的汗液会粘附在内存条的金手指上,如果内存的金手指做工不良或根本没有进行镀金工艺处理,那么内存条在使用过程中就很容易出现金手指氧化的情况,时间长了就会导致内存条与内存插槽接触不良,最后开机内存报警。对于内存条氧化造成的开机报警,我们不能简单的重新拔插一下内存了事,必须小心的使用橡皮把内存条的金手指认真擦一遍,擦得发亮为止,再插回去就可以了。
  (3).还有就是即使我们不经常使用电脑,也要每隔一个星期做到起码开机一次,让机器运行一两个小时,利用机器自身产生的热量把机器内部的潮气驱走,保持机器良好的运行状态。
  3、内存与主板兼容性不好
  这种问题最难处理,也很难确定,故障出现的周期比较频繁,但是分别测试内存条和主板时往往又发现不了问题,处理起来非常麻烦。
  解决方法:就是刷新BIOS,可能有些朋友发愁了,刷BIOS可是个难事,万一不小心主板在刷出问题,得不偿失啊,其实不然,现在的主板普遍采用两种BIOS,AMI BIOS和Award BIOS,随着软件的发展已经可以在XP下实现BIOS的软升级,具体可以参见主板说明书或者随机光盘。
  4、接触不良
  因为内存条的金手指镀金不艺不佳或经常拔插内存,导致内存在使用过程中因为接触空气而氧化生锈,逐渐的与内存插槽接触不良,最后产生开机不启动报警的故障。
  解决方法:我们只需要把内存条取下来,用橡皮把金手指上面的锈斑擦去就可以了。
  注意:我们在插内存条时一定不能用手直接接触内存条的金手指,这一来是为了防止手上的静电损伤内存条,再就是手上的汗液附着在金手指上更容易造成金手指氧化生锈。
  以上都是比较常见的故障,很容易就可以解决的。对很多熟习电脑的用户想必已经知道了,那么接下来我们看看比较有意思的故障。首页 1
········
  本书以国家人力资源和社会保障部人事考试中心2010年颁布的《全国专业技术人员计..
定价:¥39.80
优惠价:¥29.90&&《全国专业技术人员计算机应用能力考试专用教程——PowerPoint&2003中文演示文稿》以..
定价:¥39.80
优惠价:¥29.90&&
············
············
         Copyright ©
() All Rights Reserved如何定位和解决Andorid的内存溢出问题(大总结)
我们经常在做项目过程中遇到内存溢出的问题,同时面试中关于OOM的问题也常常出现。
这里,我将前辈们解决Andorid内存溢出的方法重新整理一番,方便自己以后使用。最后附上参考博文。
一、Android的内存机制
android应用层是由java开发的,android的davlik虚拟机与jvm也类似,只不过它是基于寄存器的。在java中,通过new为对象分配内存,所有对象在java堆内分配空间;而内存的释放是由垃圾收集器(GC)来回收的。 Java采用了有向图的原理。Java将引用关系考虑为图的有向边,有向边从引用者指向引用对象。线程对象可以作为有向图的起始顶点,该图就是从起始顶点(GC roots)开始的一棵树,根顶点可以到达的对象都是有效对象,GC不会回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。
二、Android的内存溢出原因
1、内存泄露导致
由于我们程序的失误,长期保持某些资源(如Context)的引用,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成内存泄露。
中常见就是Activity被引用在调用finish之后却没有释放,第二次打开activity又重新创建,这样的内存泄露不断的发生,则会导致内存的溢出。
Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。Android为不同类型的进程分配了不同的内存使用上限,如果程序在运行过程中出现了内存泄漏的而造成应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉,这使得仅仅自己的进程被kill掉,而不会影响其他进程. <span style="color:#、占用内存较多的对象
保存了多个耗用内存过大的对象(如Bitmap)或加载单个超大的图片,造成内存超出限制。
三、常见的内存泄漏问题及其解决方案
1、引用没释放造成的内存泄露
1.1注册没取消造成的内存泄露
&这种Android的内存泄露比纯Java的内存泄漏还要严重,因为其他一些Android程序可能引用系统的Android程序的对象(比如注册机制)。即使Android程序已经结束了,但是别的应用程序仍然还有对Android程序的某个对象的引用,泄漏的内存依然不能被垃圾回收。
1.2集合中对象没清理造成的内存泄露
我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
1.3 static
&static是Java中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。
&&& private static ActivitymC&&&&&& //省略
如何才能有效的避免这种引用的发生呢?
&&& 第一,应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。
&&& 第二、Context尽量使用ApplicationContext,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。
看使用的周期是否在activity周期内,如果超出,必须用application;常见的情景包括:AsyncTask,Thread,第三方库初始化等等。
还有些情景,只能用activity:比如,对话框,各种View,需要startActivity的等。
总之,尽可能使用Application。
&&& 第三、使用WeakReference代替强引用。比如可以使用WeakReference&Context&mContextR
1.4、线程(内部类的使用)
线程产生内存泄露的主要原因在于线程生命周期的不可控。如果我们的线程是Activity的内部类,所以MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,MyThread是不会被销毁的,因此它所引用的老的Activity也不会被销毁,因此就出现了内存泄露的问题。
如果非静态内部类的方法中,有生命周期大于其所在类的,那就有问题了。比如:AsyncTask、Handler,这两个类都是方便开发者执行异步任务的,但是,这两个都跳出了Activity/Fragment的生命周期。
&&& 第一、将线程的内部类,改为静态内部类。
&&&&&& 原因:
因为非静态内部类会自动持有一个所属类的实例,如果所属类的实例已经结束生命周期,但内部类的方法仍在执行,就会hold其主体(引用)。也就使主体不能被释放,亦即内存泄露。静态类编译后和非内部类是一样的,有自己独立的类名。不会悄悄引用所属类的实例,所以就不容易泄露。
&&& 第二、如果需要引用Acitivity,使用弱引用。
2、资源对象没关闭造成的内存泄露
资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。而不是等待GC来处理。它们的缓冲不仅存在于java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。因为有些资源性对象,比如SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭),如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。而且android数据库中对Cursor资源的是又限制个数的,如果不及时close掉,会导致别的地方无法获得。
3、一些不良代码成内存压力
有些代码并不造成内存泄露,但是它们,或是对没使用的内存没进行有效及时的释放,或是没有有效的利用已有的对象而是频繁的申请新内存,对内存的回收和分配造成很大影响的,容易迫使虚拟机不得不给该应用进程分配更多的内存,造成不必要的内存开支。
3.1 Bitmap没调用recycle()
Bitmap对象在不使用时,我们应该先调用recycle()释放内存,然后才设置为null.
虽然recycle()从源码上看,调用它应该能立即释放Bitmap的主要内存,但是测试结果显示它并没能立即释放内存。但是我猜应该还是能大大的加速Bitmap的主要内存的释放。
3.2 构造Adapter时,没有使用缓存的&convertView
&以构造ListView的BaseAdapter为例,在BaseAdapter中提共了方法:
public&View&getView(int&position,&View&convertView,&ViewGroup&parent)
来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list&item的view对象会被回收,然后被用来构造新出现的最下面的list&item。这个构造过程就是由getView()方法完成的,getView()的第二个形参&View&convertView就是被缓存起来的list&item的view对象(初始化时缓存中没有view对象则convertView是null)。
&&&&由此可以看出,如果我们不去使用convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费时间,也造成内存垃圾,给垃圾回收增加压力,如果垃圾回收来不及的话,虚拟机将不得不给该应用进程分配更多的内存,造成不必要的内存开支。
四、占用内存较多的对象(图片过大)造成内存溢出及其解决方案
因为Bitmap占用的内存实在是太多了,特别是分辨率大的图片,如果要显示多张那问题就更显著了。Android分配给Bitmap的大小只有8M。
方法1:等比例缩小图片
有时候,我们要显示的区域很小,没有必要将整个图片都加载出来,而只需要记载一个缩小过的图片,这时候可以设置一定的采样率,那么就可以大大减小占用的内存。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图, 因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source, decodeStream最大的秘密在于其直接调用JNI&&nativeDecodeAsset()来完成decode, 无需再使用java层的createBitmap,从而节省了java层的空间。
方法2:对图片采用软引用,及时地进行recycle()操作
虽然,系统能够确认Bitmap分配的内存最终会被销毁,但是由于它占用的内存过多,所以很可能会超过java堆的限制。因此,在用完Bitmap时,要及时的recycle掉。recycle并不能确定立即就会将Bitmap释放掉,但是会给虚拟机一个暗示:“该图片可以释放了”。
SoftReference&Bitmap&
bitmap = new SoftReference&Bitmap&(pBitmap);
if(bitmap != null){
if(bitmap.get() != null && !bitmap.get().isRecycled()){
bitmap.get().recycle();
方法3:&单个页面,横竖屏切换N次后 OOM
<span style="color:#.&看看页面布局当中有没有大的图片,比如背景图之类的。去除xml中相关设置,改在程序中设置背景图(放在onCreate()方法中):
Drawable bg = getResources().getDrawable(R.drawable.bg);
XXX.setBackgroundDrawable(rlAdDetailone_bg);
在Activity destory时注意,bg.setCallback(null);&防止Activity得不到及时的释放。
<span style="color:#.&跟上面方法相似,直接把xml配置文件加载成view&再放到一个容器里,然后直接调用 this.setContentView(View view);避免xml的重复加载。
方法4:在页面切换时尽可能少地重复使用一些代码。比如:重复调用数据库,反复使用某些对象等等.....
方法5:Android堆内存也可以自己定义大小和优化Dalvik虚拟机的内存
--http://blog.csdn.net/wenhaiyan/article/details/5519567
&&&&注意:若使用这种方法:project build target&只能选择 &= 2.2 版本,否则编译将通不过。所以不建议用这种方式。
五、Android中内存泄露监测
内存监测工具 DDMS --& Heap
使用方法比较简单:
&&&&&&&&&选择DDMS视图,并打开Devices视图和Heap视图
&&&&&&&&&点击选择要监控的进程,比如:上图中我选择的是system_process
&&&&&&&&&选中Devices视图界面上的&update heap&&图标
&&&&&&&&&点击Heap视图中的&Cause GC&&按钮(相当于向虚拟机发送了一次GC请求的操作)
在Heap视图中选择想要监控的Type,一般我们会观察dataobject的&total size的变化,正常情况下total size的值会稳定在一个有限的范围内,也就说程序中的代码良好,没有造成程序中的对象不被回收的情况。如果代码中存在没有释放对象引用的情况,那么data object的total size在每次GC之后都不会有明显的回落,随着操作次数的增加而total size也在不断的增加。(说明:选择好data object后,不断的操作应用,这样才可以看出total size的变化)。如果totalsize确实是在不断增加而没有回落,说明程序中有没有被释放的资源引用。那么我们应该怎么来定位呢?
Android中内存泄露定位
通过DDMS工具可以判断应用程序中是否存在内存泄漏的问题,那又如何定位到具体出现问题的代码片段,最终找到问题所在呢?内存分析工具MAT Memory Analyzer Tool解决了这一难题。MAT工具是一个Eclipse 插件,同时也有单独的RCP 客户端,MAT工具的解析文件是.hprof,这个文件存放了某进程的内存快照。MAT工具定位内存泄漏具体位置的方法如下:
&&&① 生成.hprof文件。Eclipse中生成.hprof文件的方法有很多,不同Android版本中生成.hprof的方式也稍有差别,但它们整体思路是一样的。我们在DDMS界面选中想要分析的应用进程,在Devices视图界面上方的一行图标按钮中,同时选中“Update Heap”和“Dump HPROF file”两个按钮,这时DDMS将会自动生成当前选中进程的.hprof文件。
&&&② 将.hprof 文件导入到MAT工具中,MAT工具会自动解析并生成报告,点击“Dominator Tree”按钮,并按包分组,选择已定义的包类点右键,在弹出的菜单中选择List objects?﹥With incoming references,这时会列出所有可疑的类。右键点击某一项,并选择Path to GC Roots?﹥excludeweak/soft references,MAT工具会进一步筛选出跟程序相关的所有内存泄漏的类。这样就可以追踪到某一个产生内存泄漏的类的具体代码中。
&&&使用MAT内存分析工具查找内存泄漏的根本思路是找到哪个类的对象的引用没有被释放,然后分析没有被释放的原因,最终定位到代码中哪些片段存在着内存泄漏。
参考博文:
http://blog.csdn.net/ronaldong99/article/details/8227818
http://articles.e-/embedded/article103890.htm
http://jackxlee./450
http://smallwoniu./8875&
正要总结的,辛苦了~
本分类共有文章18篇,更多信息详见
& 2012 - 2016 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";
/*爱悠闲底部960*75*/
var cpro_id = "u1888128";内存条有问题怎样处理
[问题点数:40分]
内存条有问题怎样处理
[问题点数:40分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2010年2月 PowerBuilder大版内专家分月排行榜第二2010年1月 PowerBuilder大版内专家分月排行榜第二2010年1月 硬件使用大版内专家分月排行榜第二2009年9月 PowerBuilder大版内专家分月排行榜第二2009年8月 PowerBuilder大版内专家分月排行榜第二2009年2月 PowerBuilder大版内专家分月排行榜第二2009年1月 PowerBuilder大版内专家分月排行榜第二2008年12月 PowerBuilder大版内专家分月排行榜第二2008年11月 PowerBuilder大版内专家分月排行榜第二2008年10月 PowerBuilder大版内专家分月排行榜第二2008年9月 PowerBuilder大版内专家分月排行榜第二2008年8月 PowerBuilder大版内专家分月排行榜第二2008年7月 PowerBuilder大版内专家分月排行榜第二2008年3月 PowerBuilder大版内专家分月排行榜第二2007年12月 PowerBuilder大版内专家分月排行榜第二
2010年3月 PowerBuilder大版内专家分月排行榜第三2009年10月 PowerBuilder大版内专家分月排行榜第三2008年5月 PowerBuilder大版内专家分月排行榜第三2008年2月 PowerBuilder大版内专家分月排行榜第三
2003年2月 Windows专区大版内专家分月排行榜第二
2003年1月 Windows专区大版内专家分月排行榜第三2002年12月 Windows专区大版内专家分月排行榜第三2002年11月 Windows专区大版内专家分月排行榜第三2002年10月 Windows专区大版内专家分月排行榜第三2002年8月 Windows专区大版内专家分月排行榜第三2003年2月 硬件使用大版内专家分月排行榜第三2003年1月 硬件使用大版内专家分月排行榜第三2002年9月 专题开发/技术/项目大版内专家分月排行榜第三
2011年1月 VB大版内专家分月排行榜第二2010年10月 VB大版内专家分月排行榜第二
2013年1月 VB大版内专家分月排行榜第三2012年12月 VB大版内专家分月排行榜第三2011年6月 VB大版内专家分月排行榜第三2011年2月 VB大版内专家分月排行榜第三2010年12月 VB大版内专家分月排行榜第三2010年11月 VB大版内专家分月排行榜第三2009年7月 VB大版内专家分月排行榜第三
2010年8月 硬件使用大版内专家分月排行榜第二
2010年7月 Windows专区大版内专家分月排行榜第三2009年1月 Windows专区大版内专家分月排行榜第三2008年12月 Windows专区大版内专家分月排行榜第三2006年8月 扩充话题大版内专家分月排行榜第三
2014年4月 Windows专区大版内专家分月排行榜第一2013年8月 Windows专区大版内专家分月排行榜第一2013年7月 Windows专区大版内专家分月排行榜第一2013年5月 Windows专区大版内专家分月排行榜第一2013年4月 Windows专区大版内专家分月排行榜第一
2014年5月 Windows专区大版内专家分月排行榜第二2013年11月 Windows专区大版内专家分月排行榜第二2013年10月 Windows专区大版内专家分月排行榜第二2013年6月 Windows专区大版内专家分月排行榜第二2013年3月 Windows专区大版内专家分月排行榜第二2006年1月 Windows专区大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。Android 内存剖析 - 发现潜在问题 - ImportNew
| 标签: , , ,
移动平台上的开发和内存管理紧密相关。尽管随着科技的进步,现今移动设备上的内存大小已经达到了低端桌面设备的水平,但是现今开发的应用程序对内存的需求也在同步增长。主要问题出在设备的屏幕尺寸上-分辨率越高需要的内存越多。熟悉Android平台的开发人员一般都知道垃圾回收器并不能彻底杜绝内存泄露问题,对于大型应用而言,内存泄露对性能产生的影响是难以估量的,因此开发人员必须要有内存分析的能力。本文介绍一些有用的工具,以及如何使用它们来检测这些关键的内存泄露问题。
有很多工具可以用来帮助检测内存泄露问题,这里列举了一些,并附上一点相应的介绍:
DDMS (Dalvik调试监视服务器)
和Android一起推出的调试工具(android sdk的tools目录下就有)。提供端口转发服务、截屏、线程监控、堆dump、logcat、进程和无线状态监控以及一些其他功能。可以通过”./ddms”命令启动该工具,同时它也被集成在ADT中,安装以后切到DDMS视图即可。
MAT (内存分析工具)
快速的Java堆分析器,该工具可以检测到内存泄露,降低内存消耗,它有着非常强大的解析堆内存空间dump能力。还有很多其他功能无法在这里一一列出,可以安装一下MAT的eclipse插件试试,要活的更多详细信息请点击。
内存分析涉及到很多专用术语,他们在本文中将频繁出现,这里给出每个术语的定义:
分配给Java堆的内存,在Android平台,这些内存都是针对每个Activity分配的(这还取决于设备)
堆转储文件
一个包含了堆中信息的二进制文件
支配树(Dominator Tree)
一个用来图形化展示对象之间关系的工具,详情请参考
内存泄露是指有个引用指向一个不再被使用的对象,导致该对象不会被垃圾回收器回收。如果这个对象有个引用指向一个包括很多其他对象的集合,就会导致这些对象都不会被垃圾回收。因此,需要牢记,垃圾回收无法杜绝内存泄露。
GC根是指那些假设可达的对象。 通常包括所有当前栈和系统的类加载器加载的类中引用的对象。(【译者注】栈里引用的对象是指当前执行的方法里的局部变量指向的对象,系统加载器加载的类引用的对象包括类的静态属性引用的对象)
内存泄露是指有个引用指向一个不再被使用的对象,导致该对象不会被垃圾回收器回收。如果这个对象有个引用指向一个包括很多其他对象的集合,就会导致这些对象都不会被垃圾回收。
浅堆(Shallow Heap)
被一个对象直接消耗的内存
public final class myObject { // 头部: 8字节
private int valueA; // 整型: 4字节
private int valueB; // 整型: 4字节
private char valueC[]; // 字符型数组: 4字节
一个myObject对象共消耗20个字节保留堆(Retained Heap)
因释放了某个对象后,可以释放的所有内存总和。
GC前:GC即将回收对象A
GC后:回收对象A(300字节)从而导致回收对象B(50字节)和C(50字节),同时释放了对象B以后对象D也会被回收(100字节),因此回收对象A就可以释放500字节的内存,所谓保留队正式这些对象直接占用的浅堆总和。
检测内存泄露
有好几种方法可以发现内存泄露,本小节介绍其中几种。
Logcat输出的log
第一种发现内存泄露的方法是检查logcat输出的log。当垃圾回收器工作时,可以在Logcat中看到它的消息,这消息长的样子类似于:
D/dalvikm( 14302): GC_CONCURRENT freed 2349K, 65% free K, external K, paused 2ms+2ms
这条消息的第一个部分说明该消息产生的原因,一共有四种类型:
GC_CONCURRENT
当堆变得很大,防止出现堆溢出异常时产生
GC_FOR_MALLOC
如果GC_CONCURENT类型的操作没有及时运行,并且应用程序还需要分配更多内存时产生。
GC_EXTERNAL_ALLOC
在Android3.0 (Honeycomb)以前,释放通过外部内存(externel memory, 通过JNI代码中malloc分配得到的内存)时产生。Android3.0和更高版本中不再有这种类型的内存分配了。
GC_EXPLICIT
调用System.gc时产生
“freed 2349K,” – 说明释放了多少内存.
“65% free K” – 65%表示目前可分配内存占比例,3426K表示当前活动对象所占内存,9551K表示堆大小。
“external K” – indicates external memory allocation, how much external memory the app has allocated and the soft limit of allocation.说明外部内存的分配,已经分配了多少以及能够分配的上限。
“paused 2ms+2ms” –说明GC运行完成需要的时间。
有了这些信息,我们就可以知道GC运行几次以后有没有成功释放出一些内存,如果分配出去的内存在这几个周期中持续增加,那么很明显存在内存泄露。下面的例子中就是存在内存泄漏时的Log。(【译者注】图片有点不清楚,但是大概可以看出来GC运行了好多次,可分配内存比例反而从47%降到45%了)
OutOfMemoryError 异常
当可用内存耗尽时,将会抛出OutOfMemoryError异常(OOM),此异常的出现说明有可能存在内存泄露,但这个办法并不是万无一失的,因为有可能开发者就是想分配一块大内存(比如处理bitmap时),并且这一大块内存的大小超出了平台限制。但是此异常的出现至少说明开发人员必须要重新考虑自己代码对内存的使用方法是不是有问题。
跟踪内存分配情况
成功的发现内存泄露问题以后,就应该查找根源在哪里了,有两个工具可以用来辅助分析问题根源所在。
DDMS是一个强大的工具,他可以提供有很价值的信息,它还可以生成一个HPROF dump文件,该文件可以使用MAT打开分析。在Eclipse中打开DDMS,只需安装ADT插件以后打开DDMS视图即可。
可以看到,界面相当直观,不需要什么详细的说明,但有两个标签页值得注意。第一个是“Allocation Tracker”,它用来显示当前内存分配的详细情况,可以看到每种数据类型(基本数据类型或者自定义类)的内存分配大小,甚至可以看到是哪个源代码文件的哪一行代码分配出去的。
第二个是“Heap”,它可以显示每个类有多少个对象,每个对象分配了多少内存。(【译者注】想要使用heap标签页work,要在左边窗口先选择自己想要监控的应用的package name,然后点击上面的工具栏点击那个绿色的小图标,从左往右数第二个,开启这项功能)。
获得HPROF dump文件很容易,连接设备,启动想要监控的应用,运行一会,点击左边设备窗口上方工具栏的“Dump HPROF File”按钮(从左往右数第三个)。如果Eclipse有安装MAT插件的话,则会自动打开此dump文件。
内存分析工具 (MAT)
MAT是个强大的内存分析工具,可以单独使用也可以作为Eclipse的插件(【译者注】这个工具不在ADT中,可以在下载,有stand-alone版本和Eclipse安装的update URL),这两种使用方法唯一的区别就是如何打开一个HPROF文件。独立版本需要一个打包好的HPROF文件。我们可以使用android adk自带的hprof-conv工具(在android sdk的tools目录下)打包。如果使用Eclipse插件版的MAT则不需要,直接在Eclipse中打开MAT视图即可。
当打开HPROF文件后,可以看到一个Overview界面,它由以下元素构成:
Overview标签页,提供一个概览界面。
Histogram视图,它提供每个类的对象统计(本文稍后详述)
支配树(Dominator Tree),提供程序中最占内存的对象 (described later in the article).
对象查询语言(Object Query Language Studio), 用来写MAT查询的工具.
专家系统测试(Expert System Test) –
堆Dump概况(Heap Dump Overview) –提供堆dump文件的详细信息
疑似泄露点(Leak Suspects) – 提供内存泄露疑点占用内存大小,被谁加载的,以及类型等详细信息。
Top Components – 提供占内存最多的对象信息,还包括可能的内存浪费信息.
查询浏览器(Query Browser) – 提供很多很有用的查询,有助于内存分析,本文将会介绍最有用的那些查询。根据地址查找对象 – 可以根据提供的一个地址查找某个特定的对象.
对象列表(List Objects) – 显示应用中所有对象,以及这些对象持有哪些其他对象和被哪些其他对象持有,(MAT会提示查询哪一个对象)。
根据类显示对象(Show Objects by Class) – 列出每个类有多少对象.
到GC根节点的路径(Path to GC Roots) – 显示到根节点的引用路径 (有好多过滤选项).
合并到GC根节点的最短路径(Merge Shortest Paths to GC Roots) –找到从GC根节点到一个对象或一组对象的共同路径。
即时支配(Immediate Dominators) &#8211; Finds and aggregates on a class level all objects dominating a given set of objects. 在给定的一组对象中,从类的层面上查找并聚合所有支配关系。(【译者注】好吧,我觉得实在有必要说一下支配的意思,支配在计算机的控制流理论中意思是假如说从起始节点到节点B的所有路径都经过节点A,则节点A支配节点B。在垃圾回收理论中应该是指从某个对象在另外一个对象的保留堆中)
显示保留集合(Show Retained Set) &#8211; 计算一个对象的保留堆大小.
饼图 &#8211; 显示持有内存最大的对象
直方图 &#8211; 显示每个类的对象数量
支配树 &#8211; 列出所有对象,并按照对象持有的保留堆大小排序
检查器 &#8211; 选择一个对象,并显示其详细信息
直方图(Histogram)
MAT最有用的工具之一,它可以列出任意一个类的实例数。查找内存泄露或者其他内存方面问题是,首先看看最有可能出问题的类,这个类有多少个实例是个比较好的选择。它支持使用正则表达式来查找某个特定的类,还可以计算出该类所有对象的保留堆最小值或者精确值。
计算保留堆大小
a) 计算保留堆最小值(Calculate Minimum Retained Size) –计算保留堆最小值,并显示在表格中.
b) 计算保留堆精确值(Calculate Precise Retained Size) – 计算保留堆精确值(这个过程需要一点时间) 并且显示在表格中.
正则表达式(Regex pattern) – 让用户查询某个特定的对象类
另外,当选择了某条显示条目后,可以通过右击弹出菜单。在诊断内存相关问题时,这个菜单是个非常重要的工具。如果开发者怀疑这里有个内存泄露,可以通过菜单直接查看该类的对象持有哪些其他对象,当然,MAT支持过滤查询结果(比如说限制被持有对象的类型)。查询结果出来时,列表通过另外一个有用的工具-&#8221;Path toGC Roots&#8221;-展示给开发人员。它支持多种过滤选项,比如说排除弱引用-这是最常见的一个选项,因为当GC运行时,被弱引用持有的对象会被GC直接回收,所以这种对象是不会造成内存泄露的,一般直接把这种信息排除。如果MAT预定义的查询不能满足用户需求的话,它还支持自己定制查询,定制的自由度非常大,拥有无限的可能。本文稍后会介绍如何高效的定制查询。
支配树(Dominator Tree)
支配树可以算是MAT中第二有用的工具,它可以将所有对象按照保留堆大小排序显示。用户可以直接在“Overview”选项页中点击“Dominator Tree”进入该工具,也可以在上面提到的菜单中选择“immediate dominators”进入该工具。前者显示dump文件中所有的对象,后者会从类的层面上查找并聚合所有支配关系。支配树有以下重要属性:
属于X的子树的对象表示X的保留对象集合。
如果X是Y的持有者,那么X的持有者也是Y的持有者。
在支配树中表示持有关系的边并不是和代码中对象之间的关系直接对应,比如代码中X持有Y,Y持有Z,在支配树中,X的子树中会有Z。
这三个属性对于理解支配树而言非常重要,一个熟练的开发人员可以通过这个工具快速的找出持有对象中哪些是不需要的以及每个对象的保留堆。
查询(Queries)
查询是用来检查对象树的基本工具,内存分析就是在许多对象中查找不希望看到的引用关系的过程-这件事听上去容易做起来难。如果可以过滤这些对象和应用关系的话可以使这项复杂的运动简单不少。一个开发人员想要成功的调试内存问题,必须掌握两个关键点。第一个是对自己的应用充分了解,如果对自己应用程序中的对象之间的关系不够了解的话,是不能找到内存问题的。第二个是掌握过滤和查找的技巧。如果开发者知道对象结构,而且也可以快速的找到想要的东西,那么找到那些异常状况将会变得容易一些。这里列出MAT工具所有内建的查询:
(【译者注】下面表格中的前两列都是MAT工具中菜单的名称)
List objects
With Outgoing References
显示选中对象持有哪些对象.
With Incoming References
显示选中对象被哪些对象持有。[如果一个类有很多不需要的实例,那么可以找到哪些对象持有该对象,让这个对象没法被回收]
Show object by class
With Outgoing References
显示选中对象持有哪些对象, 这些对象按类合并在一起排序
With Incoming References
显示选中对象被哪些对象持有.这些对象按类合并在一起排序
Path to GC Roots
With all references
显示选中对象到GC根节点的引用路径,包括所有类型引用.
Exclude weak references
显示选中对象到GC根节点的引用路径,排除了弱引用. [弱引用不会影响GC回收对象]
Exclude soft references
显示选中对象到GC根节点的引用路径,排除软引用(【译者注】软引用持有的对象在内存空间足够时,GC不回收,内存空间足够时,GC回收)
Exclude phantom references
显示选中对象到GC根节点的引用路径,排除虚引用(【译者注】虚引用是最弱的引用,get()总是返回null,当它的对象被GC回收时,GC将reference放在ReferenceQueue中,用户代码当发现这个reference在在ReferenceQueue时就知道它持有的对象已经被回收了,这时可以做一些清理工作。《》第四版,中文版,第87页写到Java的finilize方法是为了对象被回收前做清理工作,但是事实上会有隐患,虚引用正是弥补)
Merge Shortest Paths to GC Roots.
选项和“Path to GC Roots”一样
显示GC根节点到选中对象的引用路径
Java Basics
References Statistics Class Loader Explorer
显示引用和对象的统计信息,列出类加载器,包括定义的类
Customized Retained Set
计算选中对象的保留堆,排除指定的引用
Open in Dominator Tree
对选中对象生成支配树
Show as Histogram
展示任意对象的直方图
Thread Details
显示线程的详细信息和属性
Thread Overview and Stacks
Java Collections
Array Fill Ratio
输出数组中,非基本类型、非null对象个数占数组总长度的比例。
Arrays Grouped by Size
显示数组的直方图,按大小分组
Collection Fill Ratio
输出给定集合中,非基本类型、非null对象个数占集合容量的比例。
Collections Grouped by Size
显示集合的直方图,按大小分组
Extract Hash Set Values
列出指定hash集合中的元素
Extract List Values
列出指定LinkedList,ArrayList或Vector中的元素
Hash Entries
展开显示指定HashMap或Hashtable中的键值对
Map Collision Ratio
输出指定的映射集合的碰撞率
Primitive Arrays With a Constant Value
列出基本数据类型的数组,这些数组是由一个常数填充的。
Leak Identification
Component Report Top Consumers
分析可能的内存浪费或者低效使用的组件,并输出最大的那个
报告(Reports)
MAT自带有一个报告生成系统,他可以自动分析dump文件并且生成报告给用户。第一种报告叫做“泄露疑点(Leak suspects)”,MAT分析dump文件,检查是否存在一些个头大的对象被一些引用持有保持活动状态,需要注意的是,泄露疑点并不一定是真的内存泄露。第二种报告叫做“顶级组件(Top Components)“,它包括可能的内存浪费信息,占用内存大的对象以及引用的统计信息。此报告对内存优化有很大帮助。
泄露疑点报告
泄露疑点报告包括一些潜在的内存泄露信息,再次强调一下,在这里列出的对象并不一定是真正的内存泄露,但它仍然是检查内存泄露的一个绝佳起点。报告主要包括描述和到达聚点的最短路径, 第三部分(每种类型积累的对象)主要是从第二部分衍生出来的(根据类型排序)。
“到聚点的最短路径” 非常有用,它可以让开发人员快速发现到底是哪里让这些对象无法被GC回收。
顶级组件报告
这种报告包含很多有用的信息,特别是对那些想要降低内存使用的人来说。它包括涉嫌内存浪费的的对象,还包括引用的统计信息。整个报告非常简单直白,因此这里不需要过多的详细介绍了。
使用MAT检测内存泄露
本小节主要介绍如何使用MAT检测内存泄露的实践部分,因此将会提供一段会造成内存泄露的代码作为例子。
会内存泄露的样例代码
这段代码主要为了阐述内存泄露的最主要原因,并且为使用MAT提供一些素材。最常见的内存泄露主要有两种情况:第一种是一个静态引用持有一个普通内部类的实例(非嵌套类实例),这样会造成该实例一直处于活动状态,不会被GC回收。然后,每次屏幕旋转时,Activity的onCreate方法都会被执行,将会创建一个新的MainActivity对象,由于旧的引用,导致第一个Activity不会被垃圾回收。第二个案例被称为“context泄露”,这种情况比较难以发现,因为主要问题出在将应用的context交给一个静态属性,当然这个引用是强引用。
第一个内存泄露例子
这是第一个内存泄露例子的源代码,它会让第一个MainActivity类的实例无法让GC回收。当然这里的对象和类名称是随便取的,因为这仅仅是个一个例子,在真实项目的代码中是不会出现这种情况的。(【译者注】因为leakInstance是静态属性,它在第一次创建MainActivity实例时被赋予一个内部类对象,我们知道一个内部类对象是可以无条件访问外围对象的所有成员的,因此这个内部类对象会持有整个MainActivity对象,导致整个MainActivity都无法被回收)
public class MainActivity extends Activity {
//静态属性持有非静态内部类的实例--这么做非常糟糕
static MyLeakedClass leakInstance =
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Static field initialization
if (leakInstance == null)
leakInstance = new MyLeakedClass();
ImageView mView = new ImageView(this);
mView.setBackgroundResource(R.drawable.leak_background);
setContentView(mView);
*非静态内部类
class MyLeakedClass {
首先看一下这段代码的LogCat的输出。连接设备,运行logcat,启动应用,然后旋转几次手机。图17是LogCat输出的例子:
从第一次旋转开始,每次都存在3mb的差异。每次旋转后,堆的大小都涨3mb。这是有什么东西不对劲的第一个警告,然后LogCat没有显示任何释放已分配内存的信号。这时就需要检查应用程序内部内存的情况了,运行DDMS,获取HPROF文件,然后用自带的MAT打开。
主屏幕上的确显示了有什么东西导致内存泄露了-它大概长的和图18差不多。
饼图上显示,有很大一部分内存被资源文件占用-这很正常,因为任何应用都有一个GUI,但是本例子只有一个资源文件,因此问题应该应该隐藏在这里。还有两个FrameLayout实例(每个有3mb)需要检查,开发者还可以沿着一些路径还检查内存泄露问题。
基于直方图的检查
让我们看看直方图,可以看到有大量内存被分配给了bytes和Bitmpa类型,看看一个Bitmap对象的incoming references, 结果如图19所示:
有三个比较大的bitmap对象,这么看来这个本例最坏可能有两到三个内存泄露。这几个对象的内存大小符合LogCat的输出,让我们在检查一下他们到GC根节点的路径(剔除所有弱应用)。第一个bitmap对象看上去没什么问题,因为它只有一个应用指向自己,没有被任何其他对象引用,而且它正在等着被垃圾回收器回收。
第二个对象的引用有些多,但是一切看上也也正常,看上去这是一个可见的bitmap &#8211; 这就是为什么他有指向Activity和Context的引用的原因。
看来问题就出在剩下的第三个bitmap上了。它到GC根节点只有一条路径,而且它是被“leakInstance”对象持有的,正是leakInstance对象阻止了该bitmap对象被回收。
同时,在路径上还有一个MainActivity对象 &#8211; 看到MainActivity对象不奇怪,因为每次旋转都会新创建一个Activity,让我们看看到底发生了什么。首先通过正则表达式过滤器在直方图中找出MainActivity对象。
第一个不对劲的地方是有三个MainActivity实例。这当然不是说他们一定是内存泄露,但有些时候它们的生存时间倒的确比其他对象要长,所以我们看看到底是什么阻止它被垃圾回收。要做到这一点,首先列出所有有incoming reference的对象。再检查一下到GC根节点的路径。
第一个MainActivity对象有一个引用指向context和ActivityThread,因此它看上去是现在正在显示的Activity。
第二个对象只有一个引用指向自己,它正等着被垃圾回收,到目前为止,一切看上去都正常的。
现在再看第三个 &#8211; 就是它了!有个强引用指向leakInstance对象,就是它阻止了该对象被垃圾回收。
基于支配树的检查
开发者可以通过很多种方法找到内存泄露。本文只能介绍其中几种,第二个要介绍的是基于支配树视图的。打开HPROF文件的支配树视图,按照保留堆大小进行排序。正如预料的一样,最上面的是资源类对象,还有三个FrameLayout类的对象(每个3mb)以及一个Bitmap对象(1mb)。FrameLayout对象看上去嫌疑很大,因此我们首先检查它们。因为支配树已经列出了具体的对象,因此我们可以直接查看它们到GC根节点的路径。
第一个对象就是问题所在!它到GC根节点的唯一路径正是leakInstance对象,因此它是一个泄露。
第二个和第三个对象分别是当前正在显示和正在等着垃圾回收的。
让我们在看看那个bitmap对象,它也有可能是一个内存泄露。选择android.graphic.Bitmap,选择显示到GC根节点的路径,剔除所有弱引用。
bitmap类型有三个对象,每个对象到GC根节点的路径都可以查看到,上面说的情况再次重演,三个实例中的两个很显然没问题,但是第三个对象指向leakInstance,它一直都是活动状态,不会被回收。
可能还有上百条路径可以顺藤摸瓜找出最终的泄露点,应该选择哪条路径取决于不同的开发者了,不同的开发人员有对如何分析内存有着不同的见解。
第二个内存泄露例子
第二个内存泄露场景发生在application context上。它将application context传递给一个单例模式的类,并将其作为一个属性保留下来。这个操作将会使得MainActivity无法被垃圾回收。将context作为静态属性保存也会导致同样的结果,因此这种做法应该避免。为了避免重复罗嗦,这里只介绍一种查找内存泄露的方法。
下面是代码:
public class MainActivity2 extends Activity {
SingletonClass mSingletonClass =
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSingletonClass = SingletonClass.getInstance(this);
class SingletonClass {
private Context mContext =
private static SingletonClass mI
private SingletonClass(Context context) {
mContext =
public static SingletonClass getInstance(Context context) {
if (mInstance == null) {
mInstance = new SingletonClass(context);
运行了上面这个应用以后,把HPROF文件弄出来,然后用MAT打开分析,我们熟悉的概览界面又出现了:
概览界面并没有提供什么重要信息,因此开发人员需要继续自己的探索。这个例子中没有bitmap和其他资源,但是直方图显示这里有很多MainActivity对象 &#8211; 检查检查它们也许能得到更多更有价值的消息。
将手机旋转3次,直方图显示这里有4个MainActivity对象。嗯,是时候检查是不是有哪个对象阻止它们被回收了。要做到这一点,首先列出所有有incomming refrence的对象。只需要展开视图就很容易发现第一个对象就是当前正在显示的Activity(他包含指向ActivityThread的引用)。
继续列出其他两个对象的到GC根节点的路径。其中一个只有一个引用指向它自己,另外一个指向mInstance,该引用在SignletonClass中,还有一个应用指向当前显示的Activity(从mSigletonClass)。这正是一个泄露。
很明显可以看出context让垃圾回收无法回收该对象。另外还有一个问题 &#8211; 每次创建一个Acitivity实例的时候,context都被传递给SingletonClass。这是个严重的问题,因为context引用指向一个不在需要的Activity,从而让这个Activity保持活跃无法被回收。在比较大的项目中,这中情况可能会导致一些意象不到的行为,并且这种问题很难被检查出来。
英文原文:,翻译: -
译文链接:
【如需转载,请在正文中标注并保留原文链接、译文链接和译者等信息,谢谢合作!】
关于作者:
一个不甘寂寞,热爱Java技术,喜欢Android平台,略懂密码技术,技术兴趣广泛,有些闷骚的胖子码农.
关于ImportNew
ImportNew 专注于 Java 技术分享。于日 11:11正式上线。是的,这是一个很特别的时刻 :)
ImportNew 由两个 Java 关键字 import 和 new 组成,意指:Java 开发者学习新知识的网站。 import 可认为是学习和吸收, new 则可认为是新知识、新技术圈子和新朋友……
新浪微博:
推荐微信号
反馈建议:@
广告与商务合作QQ:
&#8211; 好的话题、有启发的回复、值得信赖的圈子
&#8211; 写了文章?看干货?去头条!
&#8211; 为IT单身男女服务的征婚传播平台
&#8211; 优秀的工具资源导航
&#8211; 活跃 &#038; 专业的翻译小组
&#8211; 国内外的精选博客文章
&#8211; UI,网页,交互和用户体验
&#8211; JavaScript, HTML5, CSS
&#8211; 专注Android技术分享
&#8211; 专注iOS技术分享
&#8211; 专注Java技术分享
&#8211; 专注Python技术分享
& 2016 ImportNew

我要回帖

更多关于 4g内存条价格 的文章

 

随机推荐