导航:首页 > 操作系统 > androidmemoryfile

androidmemoryfile

发布时间:2022-10-18 00:37:18

android 内存溢出怎么解决

Android虽然会自动管理内存,java也有garbage collection (GC )内存回收机制。 但是如果程序在一次操作中打开几个M的文件,那么通常会出现下面的错误信息。 02-04 21:46:08.703: ERROR/dalvikvm-heap(2429): 1920000-byte external allocation too large for this process. 或 02-04 21:52:28.463: ERROR/AndroidRuntime(2429): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 移动终端因为内存有限,往往图片处理经常出现上述的错误。 解决方法: 1.明确调用System.gc(); 这种内存回收会有一定的作用,但是请不要太期待。 2.图片处理完成后回收内存。 请在调用BitMap进行图片处理后进行内存回收。 bitmap.recycle(); 这样会把刚刚用过的图片占用的内存释放。 3.图片处理时指定大小。 下面这个方法处理几个M的图片时是必须的 BitMap getBitpMap(){ ParcelFileDescriptor pfd; try{ pfd = mCon.getContentResolver().openFileDescriptor(uri, "r"); }catch (IOException ex){ return null; } java.io.FileDescriptor fd = pfd.getFileDescriptor(); BitmapFactory.Options options = new BitmapFactory.Options(); //先指定原始大小 options.inSampleSize = 1; //只进行大小判断 options.inJustDecodeBounds = true; //调用此方法得到options得到图片的大小 BitmapFactory.decodeFileDescriptor(fd, null, options); //我们的目标是在800pixel的画面上显示。 //所以需要调用computeSampleSize得到图片缩放的比例 options.inSampleSize = computeSampleSize(options, 800); //OK,我们得到了缩放的比例,现在开始正式读入BitMap数据 options.inJustDecodeBounds = false; options.inDither = false; options.inPreferredConfig = Bitmap.Config.ARGB_8888; //根据options参数,减少所需要的内存 Bitmap sourceBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options); return sourceBitmap; } //这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如2即1/2,3即1/3 static int computeSampleSize(BitmapFactory.Options options, int target) { int w = options.outWidth; int h = options.outHeight; int candidateW = w / target; int candidateH = h / target; int candidate = Math.max(candidateW, candidateH); if (candidate == 0) return 1; if (candidate > 1) { if ((w > target) && (w / candidate) < target) candidate -= 1; } if (candidate > 1) { if ((h > target) && (h / candidate) < target) candidate -= 1; } if (VERBOSE) Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate + "(" + (w/candidate) + " / " + (h/candidate)); return candidate; }

麻烦采纳,谢谢!

Ⅱ 如何检查 Android 应用的内存使用情况

解析日志信息
最简单的调查应用内存使用情况的地方就是Dalvik日志信息。可以在logcat(输出信息可以在Device Monitor或者IDE中查看到,例如Eclipse和Android Studio)中找到这些日志信息。每次有垃圾回收发生,logcat会打印出带有下面信息的日志消息:

Java

1

D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>

GC原因
触发垃圾回收执行的原因和垃圾回收的类型。原因主要包括:
GC_CONCURRENT
并发垃圾回收,当堆开始填满时触发来释放内存。
GC_FOR_MALLOC
堆已经满了时应用再去尝试分配内存触发的垃圾回收,这时系统必须暂停应用运行来回收内存。
GC_HPROF_DUMP_HEAP
创建HPROF文件来分析应用时触发的垃圾回收。
GC_EXPLICIT
显式垃圾回收,例如当调用 gc()(应该避免手动调用而是要让垃圾回收器在需要时主动调用)时会触发。
GC_EXTERNAL_ALLOC
这种只会在API 10和更低的版本(新版本内存都只在Dalvik堆中分配)中会有。回收外部分配的内存(例如存储在本地内存或NIO字节缓冲区的像素数据)。
释放数量
执行垃圾回收后内存释放的数量。
堆状态
空闲的百分比和(活动对象的数量)/(总的堆大小)。
外部内存状态
API 10和更低版本中的外部分配的内存(分配的内存大小)/(回收发生时的限制值)。
暂停时间
越大的堆的暂停时间就越长。并发回收暂停时间分为两部分:一部分在回收开始时,另一部分在回收将近结束时。
例如:

Java

1

D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/K, paused 2ms+2ms

随着这些日志消息的增多,注意堆状态(上面例子中的3571K/9991K)的变化。如果值一直增大并且不会减小下来,那么就可能有内存泄露了。
查看堆的更新
为了得到应用内存的使用类型和时间,可以在Device Monitor中实时查看应用堆的更新:
1.打开Device Monitor。
从<sdk>/tools/路径下加载monitor工具。
2.在Debug Monitor窗口,从左边的进程列表中选择要查看的应用进程。
3.点击进程列表上面的Update Heap。
4.在右侧面板中选择Heap标签页。

Heap视图显示了堆内存使用的基本状况,每次垃圾回收后会更新。要看更新后的状态,点击Gause GC按钮。

图1.Device Monitor工具显示[1] Update Heap和 [2] Cause GC按钮。右边的Heap标签页显示堆的情况。
跟踪内存分配
当要减少内存问题时,应该使用Allocation Tracker来更好的了解内存消耗大户在哪分配。Allocation Tracker不仅在查看内存的具体使用上很有用,也可以分析应用中的关键代码路径,例如滑动。
例如,在应用中滑动列表时跟踪内存分配,可以看到内存分配的动作,包括在哪些线程上分配和哪里进行的分配。这对优化代码路径来减轻工作量和改善UI流畅性都极其有用。
使用Allocation Tracker:
1.打开Device Monitor 。
从<sdk>/tools/路径下加载monitor工具。
2.在DDMS窗口,从左侧面板选择应用进程。
3.在右侧面板中选择Allocation Tracker标签页。
4.点击Start Tracking。
5.执行应用到需要分析的代码路径处。
6.点击Get Allocations来更新分配列表。
列表显示了所有的当前分配和512大小限制的环形缓冲区的情况。点击行可以查看分配的堆栈跟踪信息。堆栈不只显示了分配的对象类型,还显示了属于哪个线程哪个类哪个文件和哪一行。

图2. Device Monitor工具显示了在Allocation Tracker中当前应用的内存分配和堆栈跟踪的情况。
注意:总会有一些分配是来自与 DdmVmInternal 和 allocation tracker本身。
尽管移除掉所有严重影响性能的代码是不必要的(也是不可能的),但是allocation tracker还是可以帮助定位代码中的严重问题。例如,应用可能在每个draw操作上创建新的Paint对象。把对象改成全局变量就是一个很简单的改善性能的修改。
查看总体内存分配
为了进一步的分析,查看应用内存中不同内存类型的分配情况,可以使用下面的 adb 命令

Java

1

adb shell mpsys meminfo <package_name>

应用当前的内存分配输出列表,单位是千字节。
当查看这些信息时,应当熟悉下面的分配类型:
私有(Clean and Dirty) 内存
进程独占的内存。也就是应用进程销毁时系统可以直接回收的内存容量。通常来说,“private dirty”内存是其最重要的部分,因为只被自己的进程使用。它只在内存中存储,因此不能做分页存储到外存(Android不支持swap)。所有分配的Dalvik堆和本地堆都是“private dirty”内存;Dalvik堆和本地堆中和Zygote进程共享的部分是共享dirty内存。
实际使用内存 (PSS)
这是另一种应用内存使用的计算方式,把跨进程的共享页也计算在内。任何独占的内存页直接计算它的PSS值,而和其它进程共享的页则按照共享的比例计算PSS值。例如,在两个进程间共享的页,计算进每个进程PPS的值是它的一半大小。
PSS计算方式的一个好处是:把所有进程的PSS值加起来就可以确定所有进程总共占用的内存。这意味着用PSS来计算进程的实际内存使用、进程间对比内存使用和总共剩余内存大小是很好的方式。
例如,下面是平板设备中Gmail进程的输出信息。它显示了很多信息,但是具体要讲解的是下面列出的一些关键信息。
注意:实际看到的信息可能和这里的稍有不同,输出的详细信息可能会根据平台版本的不同而不同。

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

** MEMINFO in pid 9953 [com.google.android.gm] **
Pss Pss Shared Private Shared Private Heap Heap Heap
Total Clean Dirty Dirty Clean Clean Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------ ------
Native Heap 0 0 0 0 0 0 7800 7637(6) 126
Dalvik Heap 5110(3) 0 4136 4988(3) 0 0 9168 8958(6) 210
Dalvik Other 2850 0 2684 2772 0 0
Stack 36 0 8 36 0 0
Cursor 136 0 0 136 0 0
Ashmem 12 0 28 0 0 0
Other dev 380 0 24 376 0 4
.so mmap 5443(5) 1996 2584 2664(5) 5788 1996(5)
.apk mmap 235 32 0 0 1252 32
.ttf mmap 36 12 0 0 88 12
.dex mmap 3019(5) 2148 0 0 8936 2148(5)
Other mmap 107 0 8 8 324 68
Unknown 6994(4) 0 252 6992(4) 0 0
TOTAL 24358(1) 4188 9724 17972(2)16388 4260(2)16968 16595 336

Objects
Views: 426 ViewRootImpl: 3(8)
AppContexts: 6(7) Activities: 2(7)
Assets: 2 AssetManagers: 2
Local Binders: 64 Proxy Binders: 34
Death Recipients: 0
OpenSSL Sockets: 1

SQL
MEMORY_USED: 1739
PAGECACHE_OVERFLOW: 1164 MALLOC_SIZE: 62

通常来说,只需关心Pss Total列和Private Dirty列就可以了。在一些情况下,Private Clean列和Heap Alloc列也会提供很有用的信息。下面是一些应该查看的内存分配类型(行中列出的类型):
Dalvik Heap
应用中Dalvik分配使用的内存。Pss Total包含所有的Zygote分配(如上面PSS定义所描述的,共享跨进程的加权)。Private Dirty是应用堆独占的内存大小,包含了独自分配的部分和应用进程从Zygote复制分裂时被修改的Zygote分配的内存页。
注意:新平台版本有Dalvik Other这一项。Dalvik Heap中的Pss Total和Private Dirty不包括Dalvik的开销,例如即时编译(JIT)和垃圾回收(GC),然而老版本都包含在Dalvik的开销里面。
Heap Alloc是应用中Dalvik堆和本地堆已经分配使用的大小。它的值比Pss Total和Private Dirty大,因为进程是从Zygote中复制分裂出来的,包含了进程共享的分配部分。
.so mmap和.dex mmap
mmap映射的.so(本地) 和.dex(Dalvik)代码使用的内存。Pss Total 包含了跨应用共享的平台代码;Private Clean是应用独享的代码。通常来说,实际映射的内存大小要大一点——这里显示的内存大小是执行了当前操作后应用使用的内存大小。然而,.so mmap 的private dirty比较大,这是由于在加载到最终地址时已经为本地代码分配好了内存空间。
Unknown
无法归类到其它项的内存页。目前,这主要包含大部分的本地分配,就是那些在工具收集数据时由于地址空间布局随机化(Address Space Layout Randomization ,ASLR)不能被计算在内的部分。和Dalvik堆一样, Unknown中的Pss Total把和Zygote共享的部分计算在内,Unknown中的Private Dirty只计算应用独自使用的内存。
TOTAL
进程总使用的实际使用内存(PSS),是上面所有PSS项的总和。它表明了进程总的内存使用量,可以直接用来和其它进程或总的可以内存进行比较。
Private Dirty和Private Clean是进程独自占用的总内存,不会和其它进程共享。当进程销毁时,它们(特别是Private Dirty)占用的内存会重新释放回系统。Dirty内存是已经被修改的内存页,因此必须常驻内存(因为没有swap);Clean内存是已经映射持久文件使用的内存页(例如正在被执行的代码),因此一段时间不使用的话就可以置换出去。
ViewRootImpl
进程中活动的根视图的数量。每个根视图与一个窗口关联,因此可以帮助确定涉及对话框和窗口的内存泄露。
AppContexts和Activities
当前驻留在进程中的Context和Activity对象的数量。可以很快的确认常见的由于静态引用而不能被垃圾回收的泄露的 Activity对象。这些对象通常有很多其它相关联的分配,因此这是追查大的内存泄露的很好办法。
注意:View 和 Drawable 对象也持有所在Activity的引用,因此,持有View 或 Drawable 对象也可能会导致应用Activity泄露。
获取堆转储
堆转储是应用堆中所有对象的快照,以二进制文件HPROF的形式存储。应用堆转储提供了应用堆的整体状态,因此在查看堆更新的同时,可以跟踪可能已经确认的问题。
检索堆转储:
1.打开Device Monitor。
从<sdk>/tools/路径下加载monitor工具。
2.在DDMS窗口,从左侧面板选择应用进程。
3.点击Dump HPROF file,显示见图3。
4.在弹出的窗口中,命名HPROF文件,选择存放位置,然后点击Save。

图3.Device Monitor工具显示了[1] Dump HPROF file按钮。
如果需要能更精确定位问题的堆转储,可以在应用代码中调用mpHprofData()来生成堆转储。
堆转储的格式基本相同,但与Java HPROF文件不完全相同。Android堆转储的主要不同是由于很多的内存分配是在Zygote进程中。但是由于Zygote的内存分配是所有应用进程共享的,这些对分析应用堆没什么关系。
为了分析堆转储,你需要像jhat或Eclipse内存分析工具(MAT)一样的标准工具。当然,第一步需要做的是把HPROF文件从Android的文件格式转换成J2SE HRPOF的文件格式。可以使用<sdk>/platform-tools/路径下的hprof-conv工具来转换。hprof-conv的使用很简单,只要带上两个参数就可以:原始的HPROF文件和转换后的HPROF文件的存放位置。例如:

Java

1

hprof-conv heap-original.hprof heap-converted.hprof

注意:如果使用的是集成在Eclipse中的DDMS,那么就不需要再执行HPROF转换操作——默认已经转换过了。
现在就可以在MAT中加载转换过的HPROF文件了,或者是在可以解析J2SE HPROF格式的其它堆分析工具中加载。
分析应用堆时,应该查找由下导致的内存泄露:
对Activity、Context、View、Drawable的长期引用,以及其它可能持有Activity或Context容器引用的对象
非静态内部类(例如持有Activity实例的Runnable)
不必要的长期持有对象的缓存
使用Eclipse内存分析工具
Eclipse内存分析工具(MAT)是一个可以分析堆转储的工具。它是一个功能相当强大的工具,功能远远超过这篇文档的介绍,这里只是一些入门的介绍。

在MAT中打开类型转换过的HPROF文件,在总览界面会看到一张饼状图,它展示了占用堆的最大对象。在图表下面是几个功能的链接:
Histogram view显示所有类的列表和每个类有多少实例。
正常来说类的实例的数量应该是确定的,可以用这个视图找到额外的类的实例。例如,一个常见的源码泄露就是Activity类有额外的实例,而正确的是在同一时间应该只有一个实例。要找到特定类的实例,在列表顶部的<Regex>域中输入类名查找。
当一个类有太多的实例时,右击选择List objects>with incoming references。在显示的列表中,通过右击选择Path To GC Roots> exclude weak references来确定保留的实例。
Dominator tree是按照保留堆大小来显示的对象列表。
应该注意的是那些保留的部分堆大小粗略等于通过GC logs、heap updates或allocation tracker观察到的泄露大小的对象。
当看到可疑项时,右击选择Path To GC Roots>exclude weak references。打开新的标签页,标签页中列出了可疑泄露的对象的引用。
注意:在靠近饼状图中大块堆的顶部,大部分应用会显示Resources的实例,但这通常只是因为在应用使用了很多res/路径下的资源。

图4.MAT显示了Histogram view和搜索”MainActivity”的结果。
想要获得更多关于MAT的信息,请观看2011年Google I/O大会的演讲–《Android 应用内存管理》(Memory management for Android apps),在大约21:10 的时候有关于MAT的实战演讲。也可以参考文档《Eclipse 内存分析文档》(Eclipse Memory Analyzer documentation)。
对比堆转储
为了查看内存分配的变化,比较不同时间点应用的堆状态是很有用的方法。对比两个堆转储可以使用MAT:
1.按照上面描述得到两个HPROF文件,具体查看获取堆转储章节。
2.在MAT中打开第一个HPROF文件(File>Open Heap Dump)。
3.在Navigation History视图(如果不可见,选择Window>Navigation History),右击Histogram,选择Add to Comp are Basket。
4.打开第二个HRPOF文件,重复步骤2和3。
5.切换到Compare Basket视图,点击Compare the Results(在视图右上角的红色“!”图标)。
触发内存泄露
使用上述描述工具的同时,还应该对应用代码做压力测试来尝试复现内存泄露。一个检查应用潜在内存泄露的方法,就是在检查堆之前先运行一会。泄露会慢慢达到分配堆的大小的上限值。当然,泄露越小,就要运行应用越长的时间来复现。
也可以使用下面的方法来触发内存泄露:
1.在不同Activity状态时,重复做横竖屏切换操作。旋转屏幕可能导致应用泄露 Activity、Context 或 View对象,因为系统会重新创建 Activity,如果应用在其它地方持有这些对象的引用,那么系统就不能回收它们。
2.在不同Activity状态时,做切换应用操作(切换到主屏幕,然后回到应用中)。
提示:也可以使用monkey测试来执行上述步骤。想要获得更多运行 monkey 测试的信息,请查阅 monkeyrunner 文档。

Ⅲ 如何用MAT分析Android应用内存泄露

1、新建测试应用

1
新建一个Android 测试应用。
填写好应用的名称,以及保存位置后,直接下一步到最后点击“Finish”。

2
添加一个测试Activity:Activity2。

3
添加测试代码ActivityHelper:
这里用常用的线程长时间执行,导致外部Activity Destroy时还持有 activity的内容导致内存泄露。
主要代码如下:
public class ActivityHelper {
private Context mContext;
public ActivityHelper(Context context) {
this.mContext=context;
}
/** * 打印ActivityName */
public void printActivityName() {
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true)
try {
Thread.sleep(1000*30);
Log.d(ActivityHelper.class.getSimpleName(), ((Activity) mContext).getClass().getSimpleName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}}

4
在Activity2中的onCreate方法中调用单例:
new ActivityHelper().printActivityName();
然后再MainActivity中点击“Setting”菜单栏打开Activity2:
Intent intent=new Intent(MainActivity.this,Activity2.class);startActivity(intent);
最后按返回键返回。
按照以上操作,运行程序。

5
多次进入Activity2之后会发现内存一直在增长,并没有降低。
而且log里会不停的输出log,打印当前activity的name

END
2、抓取内存信息

1
点击Android Studio工具栏上得“Android Device Monitor”,打开后如图:

2
先在android设备上打开我们的应用
然后在devices里选中我们测试的应用,点击“update heap”

3
来回点击“settings”进入Activity2数次后,点击
“DUMP HPROF file”保存文件。

4
转换HPROF文件。
利用android sdk 的工具进行转换:
到sdk/platform-tools/目录下,打开终端输入:
./hprof-conv
/Users/xxx/Desktop/gc/com.lulee007.androidmemoryleakdemo.hprof
/Users/xxx/Desktop/gc/com.lulee007.androidmemoryleakdemo.out.hprof
进行转换.
最终得到这个文件:com.lulee007.androidmemoryleakdemo.out.hprof

END
3、使用Memory Analyzer 分析

下载Memory Analyzer 工具:
到官网下载:

选择合适的版本。

打开软件:
从工具栏打开phrof文件选择“File”>>"open heap mp"

点击下面的“Action”里的“Histogram”,然后搜索ActivityHelper
得到如下结果

右击其中的一个,选择“Merge Shortest Paths to GC Roots ”>>"exclude all phantom/weak/soft etc references.."

可以看到,ActivityHelper本应该被释放,但是因为thead持有其中的mContext,而context是activity2里的,所有造成了内存泄露。
解决方法:
合理用thread,当activity2,destroy时,需要及时的停止掉thread。
可以设置activityhelper的while(true)改为设置变量,如while(notshutdown),
然后再destory里调用activityhelper,设置其notshutdown为false即可。

Ⅳ android手机测试中如何查看内存泄露

如何查看内存泄露

主要有2种方法

  1. 借助工具,查看。

  2. 借助adb 命令来查看。

【主要原理】

借助工具来查看泄露的原因。

详细实现方式

【工具查看】

常用工具有很多例如:

1.功能强大PC端检测工具,如MemoryAnalyzer运行在PC端抓取Android手机中的mp文件进行深度分析。

2.小而优的Android端检测工具,如LeakCanary随App一起安装会在Android手机桌面安装的内存泄露检测App

详细的介绍网络里面非常多这边不做过多的介绍。

3.还有一种,要求不高的可以通过android studio查看内存变化等

详细看到界面,视图等占用的内存情况。

【最后】

2种方法相互使用,验证内存泄露原因。

Ⅳ 如何偷Android的内存

MemoryFile是android在最开始就引入的一套框架,其内部实际上是封装了android特有的内存共享机制Ashmem匿名共享内存,简单来说,Ashmem在Android内核中是被注册成一个特殊的字符设备,Ashmem驱动通过在内核的一个自定义slab缓冲区中初始化一段内存区域,然后通过mmap把申请的内存映射到用户的进程空间中(通过tmpfs),这样子就可以在用户进程中使用这里申请的内存了,另外,Ashmem的一个特性就是可以在系统内存不足的时候,回收掉被标记为”unpin”的内存,这个后面会讲到,另外,MemoryFile也可以通过Binder跨进程调用来让两个进程共享一段内存区域。由于整个申请内存的过程并不再Java层上,可以很明显的看出使用MemoryFile申请的内存实际上是并不会占用Java堆内存的。
MemoryFile暴露出来的用户接口可以说跟他的名字一样,基本上跟我们平时的文件的读写基本一致,也可以使用InputStream和OutputStream来对其进行读写等操作:

1
2
3
4

MemoryFile memoryFile = new MemoryFile(null, inputStream.available());
memoryFile.allowPurging(false);
OutputStream outputStream = memoryFile.getOutputStream();
outputStream.write(1024);

上面可以看到allowPurging这个调用,这个就是之前说的”pin”和”unpin”,在设置了allowPurging为false之后,这个MemoryFile对应的Ashmem就会被标记成”pin”,那么即使在android系统内存不足的时候,也不会对这段内存进行回收。另外,由于Ashmem默认都是”unpin”的,因此申请的内存在某个时间点内都可能会被回收掉,这个时候是不可以再读写了
Tricks
MemoryFile是一个非常trickly的东西,由于并不占用Java堆内存,我们可以将一些对象用MemoryFile来保存起来避免GC,另外,这里可能android上有个BUG:
在4.4及其以上的系统中,如果在应用中使用了MemoryFile,那么在mpsys meminfo的时候,可以看到多了一项Ashmem的值:

可以看出来虽然MemoryFile申请的内存不计入Java堆也不计入Native堆中,但是占用了Ashmem的内存,这个实际上是算入了app当前占用的内存当中
但是在4.4以下的机器中时,使用MemoryFile申请的内存居然是不算入app的内存中的:

而且这里我也算过,也是不算入Native Heap中的,另外,这个时候去系统设置里面看进程的内存占用,也可以看出来其实并没有计入Ashmem的内存的
这个应该是android的一个BUG,但是我搜了一下并没有搜到对应的issue,搞不好这里也可能是一个feature
而在大名鼎鼎的Fresco当中,他们也有用到这个bug来避免在decode bitmap的时候,将文件的字节读到Java堆中,使用了MemoryFile,并利用了这个BUG然这部分内存不算入app中,这里分别对应了Fresco中的GingerbreadPurgeableDecoder和KitKatPurgeableDecoder,Fresco在decode图片的时候会在4.4和4.4以下的系统中分别使用这两个不同的decoder
从这个地方可以看出来,使用MemoryFile,在4.4以下的系统当中,可以帮我们的app额外”偷”一些内存,并且可以不计入app的内存当中
Summary
这里主要是简单介绍了MemoryFile的基本原理和用法,并且阐述了一个MemoryFile中一个可以帮助开发者”偷”内存的地方,这个是一个非常trickly的方法,虽然4.4以下使用这块的内存并不计入进程当中,但是并不推荐大量使用,因为当设置了allowPurging为false的时候,这个对应的Ashmem内存区域是被”pin”了,那么在android系统内存不足的时候,是不能够把这段内存区域回收的,如果长时间没有释放的话,这样子相当于无端端占用了大量手机内存而又无法回收,那对系统的稳定性肯定会造成影响

Ⅵ Android获取系统cpu信息,内存,版本,电量等信息

1、CPU频率,CPU信息:/proc/cpuinfo和/proc/stat

通过读取文件/proc/cpuinfo系统CPU的类型等多种信息。

读取/proc/stat 所有CPU活动的信息来计算CPU使用率

下面我们就来讲讲如何通过代码来获取CPU频率:

复制代码 代码如下:

package com.orange.cpu;

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.InputStream;

public class CpuManager {

// 获取CPU最大频率(单位KHZ)

// "/system/bin/cat" 命令行

// "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" 存储最大频率的文件的.路径

public static String getMaxCpuFreq() {

String result = "";

ProcessBuilder cmd;

try {

String[] args = { "/system/bin/cat",

"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" };

cmd = new ProcessBuilder(args);

Process process = cmd.start();

InputStream in = process.getInputStream();

byte[] re = new byte[24];

while (in.read(re) != -1) {

result = result + new String(re);

}

in.close();

} catch (IOException ex) {

ex.printStackTrace();

result = "N/A";

}

return result.trim();

}

// 获取CPU最小频率(单位KHZ)

public static String getMinCpuFreq() {

String result = "";

ProcessBuilder cmd;

try {

String[] args = { "/system/bin/cat",

"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq" };

cmd = new ProcessBuilder(args);

Process process = cmd.start();

InputStream in = process.getInputStream();

byte[] re = new byte[24];

while (in.read(re) != -1) {

result = result + new String(re);

}

in.close();

} catch (IOException ex) {

ex.printStackTrace();

result = "N/A";

}

return result.trim();

}

// 实时获取CPU当前频率(单位KHZ)

public static String getCurCpuFreq() {

String result = "N/A";

try {

FileReader fr = new FileReader(

"/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");

BufferedReader br = new BufferedReader(fr);

String text = br.readLine();

result = text.trim();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return result;

}

// 获取CPU名字

public static String getCpuName() {

try {

FileReader fr = new FileReader("/proc/cpuinfo");

BufferedReader br = new BufferedReader(fr);

String text = br.readLine();

String[] array = text.split(":s+", 2);

for (int i = 0; i < array.length; i++) {

}

return array[1];

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

}

2、内存:/proc/meminfo

复制代码 代码如下:

public void getTotalMemory() {

String str1 = "/proc/meminfo";

String str2="";

try {

FileReader fr = new FileReader(str1);

BufferedReader localBufferedReader = new BufferedReader(fr, 8192);

while ((str2 = localBufferedReader.readLine()) != null) {

Log.i(TAG, "---" + str2);

}

} catch (IOException e) {

}

}

3、Rom大小

复制代码 代码如下:

public long[] getRomMemroy() {

long[] romInfo = new long[2];

//Total rom memory

romInfo[0] = getTotalInternalMemorySize();

//Available rom memory

File path = Environment.getDataDirectory();

StatFs stat = new StatFs(path.getPath());

long blockSize = stat.getBlockSize();

long availableBlocks = stat.getAvailableBlocks();

romInfo[1] = blockSize * availableBlocks;

getVersion();

return romInfo;

}

public long getTotalInternalMemorySize() {

File path = Environment.getDataDirectory();

StatFs stat = new StatFs(path.getPath());

long blockSize = stat.getBlockSize();

long totalBlocks = stat.getBlockCount();

return totalBlocks * blockSize;

}

4、sdCard大小

复制代码 代码如下:

public long[] getSDCardMemory() {

long[] sdCardInfo=new long[2];

String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) {

File sdcardDir = Environment.getExternalStorageDirectory();

StatFs sf = new StatFs(sdcardDir.getPath());

long bSize = sf.getBlockSize();

long bCount = sf.getBlockCount();

long availBlocks = sf.getAvailableBlocks();

sdCardInfo[0] = bSize * bCount;//总大小

sdCardInfo[1] = bSize * availBlocks;//可用大小

}

return sdCardInfo;

}

5、电池电量

复制代码 代码如下:

private BroadcastReceiver batteryReceiver=new BroadcastReceiver(){

@Override

public void onReceive(Context context, Intent intent) {

int level = intent.getIntExtra("level", 0);

// level加%就是当前电量了

}

};

registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

6、系统的版本信息

复制代码 代码如下:

public String[] getVersion(){

String[] version={"null","null","null","null"};

String str1 = "/proc/version";

String str2;

String[] arrayOfString;

try {

FileReader localFileReader = new FileReader(str1);

BufferedReader localBufferedReader = new BufferedReader(

localFileReader, 8192);

str2 = localBufferedReader.readLine();

arrayOfString = str2.split("s+");

version[0]=arrayOfString[2];//KernelVersion

localBufferedReader.close();

} catch (IOException e) {

}

version[1] = Build.VERSION.RELEASE;// firmware version

version[2]=Build.MODEL;//model

version[3]=Build.DISPLAY;//system version

return version;

}

7、mac地址和开机时间

复制代码 代码如下:

public String[] getOtherInfo(){

String[] other={"null","null"};

WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);

WifiInfo wifiInfo = wifiManager.getConnectionInfo();

if(wifiInfo.getMacAddress()!=null){

other[0]=wifiInfo.getMacAddress();

} else {

other[0] = "Fail";

}

other[1] = getTimes();

return other;

}

private String getTimes() {

long ut = SystemClock.elapsedRealtime() / 1000;

if (ut == 0) {

ut = 1;

}

int m = (int) ((ut / 60) % 60);

int h = (int) ((ut / 3600));

return h + " " + mContext.getString(R.string.info_times_hour) + m + " "

+ mContext.getString(R.string.info_times_minute);

}

Ⅶ android何时会发生oom怎么解决oom

首先,OOM就是内存溢出,即Out Of Memory。也就是说内存占有量超过了VM所分配的最大。
怎么解决OOM,通常OOM都发生在需要用到大量内存的情况下(创建或解析Bitmap,分配特大的数组等),在这样的一种情况下,就可能出现OOM,据我现在了解到,多数OOM都是因为Bitmap太大。所以,这里我就专门针对如何解决Bitmap的OOM。其实最核发的就是只加载可见范围内的Bitmap,试想这样一种情况,在GridView或ListView中,数据量有5000,每一屏只显示20个元素,那么不可见的,我们是不需要保存Bitmap在内在中的。所以我们就是只把那么可见的Bitmap保留在内存中,那些不可见的,就释放掉。当元素滑出来时,再去加载Bitmap。
这里我有两种方式,都可以避免OOM。

Ⅷ 如何快速定位android app是否存在内存泄露

1、首先确定是否有内存泄露及哪个程序造成。
1.1、内存泄露已弹出out of memory对话框的情况。
这种情况很简单,直接看对话框就知道是哪个应用的问题了。然后再分析该应用是否是因为内存泄露造成的
out of memory对话框。
》中介绍的各种方法进行分析,确定是否有内存泄露以及是哪个进程造成的内存泄露。
2、生成hprof文件,用MAT进行分析。
生成hprof文件可以在DDMS选中进程点击窗口左上角的mp hprof file按钮来直接生成,也可以通过在程序加代码中来生成代码2:voidgenerateHprof(){String packageName=getApplicationInfo().packageName;
StringhpFilePath=/data/data/+packageName+/input.hprof;try{//Debug.mpHprofData(/sdcard/input.hprof);Debug.
mpHprofData
(hpFilePath);}catch(IOException e) {//TODOAuto-generated catch block
e.printStackTrace();}}建议使用代码生成hprof,然后使用《
Android内存泄露利器(hprof篇)》中的工具自动提取多个hprof文件,然后用MAT进行比较分析。在MAT导入.hprof文件以后,
MAT会自动解析并生成报告,点击
Dominator Tree
,并按Package分组,选择自己所定义的Package类,比较各个类在不同时期的RetainedHeap
,找出可疑类,然后选择该类,点右键,选中
show retained Set项,参看Retained Heap
的详细信息,进一步找出嫌疑项。
3、在代码中查找内存泄露。
根据在MAT找到的内存泄露信息,参照《
Android内存泄漏简介
》进一步在内存中查找内存泄露的原因并解决。
另外如果代码很简单,可以直接参照《
Android内存泄漏简介
》在内存中查找内存泄露的原因并解决。

Ⅸ Android中如何获得外置sd卡的路径和手机自身内存的路径

你问的编码?

原文:http://blog.163.com/hero_213/blog/static/39891214201162123236660/
转载非原创。
该代码片段可以让我们获取internal和external的存储空间大小。

import java.io.File;

import android.os.Environment;
import android.os.StatFs;

public class StorageUtil {

private static final int ERROR = -1;

/**
* SDCARD是否存
*/
public static boolean externalMemoryAvailable() {
return android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
}

/**
* 获取手机内部剩余存储空间
* @return
*/
public static long () {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
}

/**
* 获取手机内部总的存储空间
* @return
*/
public static long getTotalInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return totalBlocks * blockSize;
}

/**
* 获取SDCARD剩余存储空间
* @return
*/
public static long () {
if (externalMemoryAvailable()) {
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
} else {
return ERROR;
}
}

/**
* 获取SDCARD总的存储空间
* @return
*/
public static long getTotalExternalMemorySize() {
if (externalMemoryAvailable()) {
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return totalBlocks * blockSize;
} else {
return ERROR;
}
}
}

1.硬件上的 block size, 应该是"sector size",linux的扇区大小是512byte
2.有文件系统的分区的block size, 是"block size",大小不一,可以用工具查看
3.没有文件系统的分区的block size,也叫“block size”,大小指的是1024 byte
4.Kernel buffer cache 的block size, 就是"block size",大部分PC是1024
5.磁盘分区的"cylinder size",用fdisk 可以查看。
我们这里的block size是第二种情况,一般SD卡都是fat32的文件系统,block size是4096.
这样就可以知道手机的内部存储空间和sd卡存储空间的总大小和可用大小了。

Ⅹ android scrollview内存溢出怎么解决

android scrollview内存溢出通常是由内存泄露导致。
1、内存泄露导致
由于我们程序的失误,长期保持某些资源(如Context)的引用,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成内存泄露。
Android 中常见就是Activity被引用在调用finish之后却没有释放,第二次打开activity又重新创建,这样的内存泄露不断的发生,则会导致内存的溢出。
Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。Android为不同类型的进程分配了不同的内存使用上限,如果程序在运行过程中出现了内存泄漏的而造成应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉,这使得仅仅自己的进程被kill掉,而不会影响其他进程.
2、占用内存较多的对象
保存了多个耗用内存过大的对象(如Bitmap)或加载单个超大的图片,造成内存超出限制。
使用方法比较简单:
· 选择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内存分析工具查找内存泄漏的根本思路是找到哪个类的对象的引用没有被释放,然后分析没有被释放的原因,最终定位到代码中哪些片段存在着内存泄漏。

阅读全文

与androidmemoryfile相关的资料

热点内容
搜索pdf内容 浏览:497
程序员装机必备的软件 浏览:9
php微信第三方登录demo 浏览:536
上海php工具开发源码交付 浏览:790
哪里有求购黄页的源码 浏览:194
商城矿机源码矿场系统 浏览:196
单片机的led灯熄灭程序 浏览:222
洛阳python培训 浏览:702
小键盘命令 浏览:194
单片机c语言返回主程序 浏览:816
dockerpythonweb 浏览:970
程序员算法有多强 浏览:717
pythonworkbook模块 浏览:245
什么app能查医生 浏览:175
轻量级的编程语言 浏览:338
程序员那么可爱生孩子 浏览:432
后缀him3加密文件是什么软件 浏览:986
坚果隐藏app为什么要140版本才能用 浏览:313
淘宝dns服务器地址 浏览:259
领英转型app哪个好用 浏览:943