这是一篇介绍安卓虚拟机联网时经常容易报的错误,连接成功后无限下载数据包,永远无法成功的原因。
GC_CONCURRENT 错误:当分配的对象大小超过384K时触发java回收机制,自动回收内容,联网下载的内容在内存中达到这个数时自动清理内存,无限重复下载然后删除的动作,所以这个错误导致虚拟机无法正常的链接网络。
(注:往往这个错误在实体机上不会发生)
以下是原帖内容:
老是看到LOG日志里有些系统回收的东西。明知道是内存问题。但还真不知道怎么下手。唉,无赖啊。网上找资料海里捞针,不容易啊。看到这篇不错。
1. verbosegc
一般Java虚拟机要求支持verbosegc选项,输出详细的垃圾收集调试信息。dalvik虚拟机很安静的接受verbosegc选项,然后什么都不做。dalvik虚拟机使用自己的一套LOG机制来输出调试信息。
如果在Linux下运行adb logcat命令,可以看到如下的输出:
D/dalvikvm( 745): GC_CONCURRENT
freed 199K, 53% free 3023K/6343K,external 0K/0K, paused 2ms+2ms
其中D/dalvikvm表示由dalvikvm输出的调试信息,括号后的数字代表dalvikvm所在进程的pid。
GC_CONCURRENT表示触发垃圾收集的原因,有以下几种:
- GC_MALLOC, 内存分配失败时触发
- GC_CONCURRENT,当分配的对象大小超过384K时触发
- GC_EXPLICIT,对垃圾收集的显式调用(System.gc)
- GC_EXTERNAL_ALLOC,外部内存分配失败时触发
freed 199K表示本次垃圾收集释放了199K的内存,
53% free 3023K/6343K,其中6343K表示当前内存总量,3023K表示可用内存,53%表示可用内存占总内存的比例。
external 0K/0K,表示可用外部内存/外部内存总量
paused
2ms+2ms,第一个时间值表示markrootset的时间,第二个时间值表示第二次mark的时间。如果触发原因不是GC_CONCURRENT,这一行为单个时间值,表示垃圾收集的耗时时间。
2. 分析
(1)虽然dalvikvm提供了一些调试信息,但是还缺乏一些关键信息,比如说mark和sweep的时间,
分配内存失败时是因为分配多大的内存失败,还有对于SoftReference,WeakReference和PhantomReference的处理,每次垃圾收集处理了多少个这些引用等。
(2)目前dalvik所有线程共享一个内存堆,这样在分配内存时必须在线程之间互斥,可以考虑为每个内存分配一个线程局部存储堆,一些小的内存分配可以直接从该堆中分配而无须互斥锁。
(3)dalvik虚拟机中引入了concurrentmark,但是对于多核CPU,可以实现parrelmark,即可以使用多个线程同时运行mark阶段。
这些都是目前dalvik虚拟机内存管理可以做出的改进。
出处:
http://www.cnblogs.com/bmate/archive/2012/02/02/2336169.html
一、先说DDMS中的Heap的使用,通过它可以观察VM中的Java内存,但是无法查看通过JNI分配的内存
直接上图,废话少说。。。
图一:将要查看内存使用情况的项目Update heap
图二:操作项目,通过图表可以很直观查看虚拟机的使用内存
二:Android中GC_EXTERNAL_ALLOC的含义(转)
以下内容直接Ctrl C===》Ctrl V
问:
GC_EXTERNAL_ALLOC freed 297K, 49% free 3411K/6663K, external 24870K/26260K, paused 83ms
这里边的每个数字都是什么意思阿?
free 3411K/6663K和external 24870K/26260K,分别都是表示什么的阿?
自问自答:
前面Free的内存是VM中java使用的内存,external是指VM中通过JNI中Native的类中的malloc分配出的内存,例如Bitmap和一些Cursor都是这么分配的。
在Davilk中,给一个程序分配的内存根据机型厂商的不同,而不同,现在的大部分的是32M了,而在VM内部会把这些内存分成java使用的内存和 Native使用的内存,它们之间是不能共享的,就是说当你的Native内存用完了,现在Java又有空闲的内存,这时Native会重新像VM申请,而不是直接使用java的。
例如上边的例子
free 3411K/6663K和external 24870K/26260K
如果这时需要创建一个2M的Bitmap,Native现有内存26260-24870=1390K<2048k,因此他就会向Vm申请内存,虽然java空闲的内存是
6663-3411=3252>2048,但这部分内存Native是不能使用。
但是你现在去申请2M的Native内存,VM会告诉你无法分配的,因为现在已使用的内存已经接近峰值了32M(26260+6663=32923 ),所以现在就会成force close 报OOM。
所以现在我们要检查我们的native内存的使用情况来避免OOM。
总结:通过Heap可以查看到Java使用内存情况,但是无法查看JNI使用内存的情况,所以遇到内存溢出时,项目要是调用到动态库的,就留意一下通过JNI申请的内存是否合理释放。
转:http://blog.youkuaiyun.com/zzp16/article/details/6719809