2012-09-15 16:53:02 yangxi_001 阅读数 4222

1.   Dalvik内存

每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。

很多人认为Dalvik虚拟机是一个Java虚拟机,因为Android的编程语言恰恰就是Java语言。但是这种说法并不准确,因为 Dalvik虚拟机并不是按照Java虚拟机的规范来实现的,两者并不兼容;

同时还要两个明显的不同:

  1.Java虚拟机运行的是Java字节码,而Dalvik虚拟机运行的则是其专有的文件格式DEX(Dalvik Executable)。

2.在Java SE程序中的Java类会被编译成一个或者多个字节码文件(.class)然后打包到JAR文件,而后Java虚拟机会从相应的CLASS文件和JAR文件中获取相应的字节码;Android应用虽然也是使用Java语言进行编程,但是在编译成CLASS文件后,还会通过一个工具(dx)将应用所有的 CLASS文件转换成一个DEX文件,而后Dalvik虚拟机会从其中读取指令和数据。

Dalvik虚拟机的简介:

Dalvik虚拟机主要是完成对象生命周期的管理,堆栈的管理,线程管理,安全和异常的管理,以及垃圾回收等等重要功能。

Dalvik虚拟机的主要特征Dalvik虚拟机非常适合在移动终端上使用,相对于在桌面系统和服务器系统运行的虚拟机而言,它不需要很快的CPU速度和大量的内存空间。

Dalvik虚拟机有如下几个主要特征:

1.专有的DEX文件格式

DEXDalvik虚拟机专用的文件格式,而问什么弃用已有的字节码文件(CLASS文件)而采用新的格式呢?一个应用中会定义很多类,编译完成后即会有很多相应的CLASS文件,CLASS文件间会有不少冗余的信息;而DEX文件格式会把所有的 CLASS文件内容整合到一个文件中。这样,除了减少整体的文件尺寸,I/O操作,也提高了类的查找速度。

2.增加了新的操作码的支

3.文件结构尽量简洁,使用等长的指令,借以提高解析速度

4.尽量扩大只读结构的大小,借以提高跨进程的数据共享

2.   Native内存

如何修改Android应用程序的默认最大内存值

Android应用程序的默认最大内存值为16M,有些应用程序可能会出现内存溢出,譬如ERROR/AndroidRuntime(264):java.lang.OutOfMemoryError: bitmap size exceeds VM budget

除了要检查修正代码之外,还可以考虑修改Android应用程序的默认最大内存值。

修改应用程序的默认最大内存有2种方法:

1、修改代码,适用于自己编译烧机:

当应用程序分配内存时,会调用到dalvik/vm/alloc/HeapSource.c中的dvmTrackExternalAllocation()方法,继而调用到externalAllocPossible()方法,该方法要求当前堆已使用的大小(由currentHeapSize和hs->externalBytesAllocated构成)加上我们需要再次分配的内存大小不能超过堆的最大内存值,如果超过就会报错。 

有两个地方决定了一个堆的最大内存: 

1)dalvik/vm/Init.c中的 

gDvm.heapSizeMax = 16 * 1024 * 1024;    // Spec says 75%physical mem 

2)frameworks/base/core/jni/AndroidRuntime.cpp中的 

property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4,"16m"); 

因此解决办法就是将以上2点中默认的16M改大一点,譬如32M。

2、修改配置文件,适用于烧机后的版本。

修改或添加/system/build.prop中的配置项:

dalvik.vm.heapstartsize=20m

dalvik.vm.heapgrowthlimit=200m

dalvik.vm.heapsize=320m


2018-05-12 20:58:34 qq_34071798 阅读数 190
Android Bitmap的内存分配是在Dalvik Heap而不是Native Heap

最近一直在查内存泄露问题,发现Bitmap是最容易出现内存泄露的,然后查看源码以及资料一下颠覆了我的认知观,首先以上结论是建立在Android2.3以后的版本。

首先开撸:我以ImageView --->setBackgroundResource()开始

@RemotableViewMethod
public void setBackgroundResource(int resid) {
if (resid != 0 && resid == mBackgroundResource) {
return;
}

Drawable d = null;
if (resid != 0) {
d = mContext.getDrawable(resid);
}
setBackground(d);

mBackgroundResource = resid;
}

1、上面通过Context中getDrawable(int resid)获得Drawabla

public final Drawable getDrawable(int id) {
return getResources().getDrawable(id, getTheme());
}

2、通过Context中getDrawable(int id)这个方法获取Drawable

@Nullable
public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
.....................
final Drawable res = loadDrawable(value, id, theme);
.....................
return res;
}

3、调用Resources中的loadDrawable(TypedValue value , int id , Theme theme);

     这里面有两套逻辑:这个方法中使用了缓冲技术,首先是查找缓存中是否有数据?如果是执行如下:创建Drawable

if (cs != null) {
final Drawable clonedDr = cs.newDrawable(this);

     4、如果没有,执行如下:

private Drawable loadDrawableForCookie(TypedValue value, int id, Theme theme) {
......................
dr = Drawable.createFromResourceStream(this, value, is, file, null);
..........................
}
Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);

  5、通过调用BitmapFactory.decodeStream()这个方法,通过方法可以看出调用最后进入了nativeDecodeAsset()进入了JNI层,这个就是迷惑我的地方,自认为是申请在Native层 !!!!下面让我来揭开这个神秘的面纱!

public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
.........................
bm = nativeDecodeAsset(asset, outPadding, opts);
..............
return bm;
}
    6、我们进入下面这个目录查看:Graphics.cpp
Z:\P_2016.01.18_XRobot_base_OneAndroid\frameworks\base\core\jni\android\graphics

    7、JNI代码如下:看到真实面纱没?惊讶没!反正我惊讶了!原来JNI创建Bitmap又回到了JAVA层,通过NewObject就明白了

jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets, int density)
{
.......................
jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
reinterpret_cast<jlong>(bitmap), buffer,
bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied,
ninePatchChunk, ninePatchInsets);
................
}
     故Bitmap不及时回收是Dalvik Heap容易内存泄露,而不是Native Heap。
2017-02-15 11:51:55 chillgrass 阅读数 7049

adb shell top  命令中


从以上打印可以看出,一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS 
 VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)是单个进程全部可访问的地址空间 
RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)是单个进程实际占用的内存大小,对于单个共享库, 尽管无论多少个进程使用,实际该共享库只会被装入内存一次。 
PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存) 
USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)USS 是一个非常非常有用的数字, 因为它揭示了运行一个特定进程的真实的内存增量大小。如果进程被终止, USS 就是实际被返还给系统的内存大小。 

USS 是针对某个进程开始有可疑内存泄露的情况,进行检测的最佳数字。怀疑某个程序有内存泄露可以查看这个值是否一直有增加 


Android程序内存被分为2部分:native和dalvik,dalvik就是我们平常说的java堆,我们创建的对象是在这里面分配的,而bitmap是直接在native上分配的,对于内存的限制是 native+dalvik 不能超过最大限制。Android程序内存一般限制在16M,当然也有24M的。 
 从上信息对于分析内存泄露,内存溢出都有极大的作用,从以上信息可以看到该应用程序占用的native和dalvik,当TOTAL 16407 11792 12860 22275 18459 2003超过内存最大限制时会出现OOM错误。 



dumpsys能做的事还有很多 


dumpsys [options]
               meminfo 显示内存信息
               cpuinfo 显示CPU信息
               account 显示accounts信息
               activity 显示所有的activities的信息
               window 显示键盘,窗口和它们的关系
               wifi 显示wifi信息
参考文档:http://www.cnblogs.com/qianxudetianxia/archive/2012/05/14/2497073.html 

http://www.v2ex.com/t/174185

2018-01-19 10:34:13 m0_37890492 阅读数 4526

GT一款可以对APP进行测试的软件,可以在任何情况下快速测试手机app的CPU、内存、流量、电量、帧率/流畅度等性能测试。有安卓版本和ios版本。

pss0:主程序内存;pss1:辅助程序内存。

内存情况:
total:为实际占用的内存值;
dalvik:java进程占用的堆内存;
native:程序文件运行内存;
android程序内存被分为2部分:native和dalvik,native + dalvik不能超过total。

Android内存优化

阅读数 216

没有更多推荐了,返回首页