昨天用Gallery做了一个图片浏览选择开机画面的功能,当我加载的图片多了就出现OOM问题。以前也出现过这个问题,那时候并没有深究。这次打算好好分析一下Android的内存机制。

因为我以前是做VC++开发,因此对C++在Window下的内存机制还是比较了解。不过转到Android后,一直都没有刻意去处理内存问题,因 为脑子里一直想着Java的GC机制。不过现在想想,自己对Android的GC和内存管理并不了解,自己写的代码在内存哪里运行都不清楚,心里不淡定 啊。

毕竟我以前写C++的时候,什么时候在哪里申请内存,什么时候释放内存,会不会栈溢出或者堆内存泄露都了如指掌。言归正传,今天打算先了解一下Android的堆和栈跟C++有何区别。

1、dalvik的Heap和Stack


这里说的只是dalvik  java部分的内存,实际上除了dalvik部分,还有native。这个以后再说。

下面针对上面列出的数据类型进行说明,只有了解了我们申请的数据在哪里,才能更好掌控我们自己的程序。

2、对象实例数据


实际上是保存对象实例的属性,属性的类型和对象本身的类型标记等,但是不保存实例的方法。实例的方法是属于数据指令,是保存在Stack里面,也就是上面表格里面的类方法。

对象实例在Heap中分配好以后,会在stack中保存一个4字节的Heap内存地址,用来查找对象的实例。因为在Stack里面会用到Heap的实例,特别是调用实例的时候需要传入一个this指针。

3、方法内部变量


类方法的内部变量分为两种情况:简单类型保存在Stack中;对象类型在Stack中保存地址,在Heap 中保存值。

4、非静态方法和静态方法


非静态方法有一个隐含的传入参数,这个参数是dalvik虚拟机传进去的,这个隐含参数就是对象实例在Stack中的地址指针。因此非静态方法(在 Stack中的指令代码)总是可以找到自己的专用数据(在Heap 中的对象属性值)。当然非静态方法也必须获得该隐含参数,因此非静态方法在调用前,必须先new一个对象实例,获得Stack中的地址指针,否则 dalvik虚拟机将无法将隐含参数传给非静态方法。

静态方法没有隐含参数,因此也不需要new对象,只要class文件被ClassLoader load进入JVM的Stack,该静态方法即可被调用。所以我们可以直接使用类名调用类的方法。当然此时静态方法是存取不到Heap 中的对象属性的。

5、静态属性和动态属性


静态属性是保存在Stack中的,而不同于动态属性保存在Heap 中。正因为都是在Stack中,而Stack中指令和数据都是定长的,因此很容易算出偏移量,所以类方法(静态和非静态)都可以访问到类的静态属性。也正 因为静态属性被保存在Stack中,所以具有了全局属性。

6、总结


Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和 multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事 先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较 慢。

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些 基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。

对比上面的解析可以看出,其实Java处理Heap和Stack的大致原理跟C++是一样的。只是多了一个内存回收机制,让程序员不用主动调用delete释放内存。就像在C++里面,一般使用new申请的内存才会放到堆里面,而一般的临时变量都是放到栈里面去。

今天主要是说说Android的dalvik里面的堆和栈的区别,以及存放哪些数据。粗了dalvik内存外, Android还有个native内存的概念。这个下次会继续讲解。我刚开始分析Android的内存机制,如果阅读过程中发现任何问题请留言指出,谢谢!


想了解最新移动开发资讯,最前沿的移动开发技术吗?微信搜“eoe”或扫描二维码关注eoe公众账号即可。公众账号支持绑定社区、签到及Ping功能。您也可以下载eoe客户端,随时随地看资讯读博客。

最新文章

  1. xamarin.forms 版本自动更新(针对android)
  2. 移动端前端笔记 — 遇到的常见JS与CSS问题及解决方法 ( 摘自zdwzdwzdw)
  3. notepad++和sublime 常用插件及主题
  4. 14 BasicHashTable基本哈希表类(一)——Live555源码阅读(一)基本组件类
  5. Shell.xaml
  6. C#中的async和await
  7. C++标准库异常类
  8. echo date
  9. Hibernate逍遥游记-第6章 通过Hibernate操纵对象(select-before-update)
  10. (原+转)ubuntu终端输出彩色文字
  11. Nyoj 星际之门(一)(Cayley定理)
  12. hdu4324 Triangle LOVE (拓扑排序)
  13. YUM更换源(1)--yum找不到安装包
  14. 长沙JavaEE培训机构哪家比较靠谱?Java培训的职业前景
  15. Java排序算法之快速排序
  16. C++ opentracing zipkin
  17. 使用 NPOI 导出 Excel 文件
  18. WindowsPE权威指南 第二章 小工具 PEComp代码的C语言实现
  19. Arch Linux安装后的一些初始设置简介
  20. AJAX从入门到放弃(一)

热门文章

  1. Leetcode617.Merge Two Binary Trees合并二叉树
  2. CSS(前)篇
  3. 修改Eclipse自动换行长度
  4. Android——兼容性
  5. Unicode, UTF-8, GBK, ASCII的区别
  6. 工程没有生成lib文件,只生成了dll文件
  7. 移动端的touch事件(一)
  8. LintCode_68 二叉树后序遍历
  9. CSS user-select文本是否可复制
  10. Unrecognised tag: 'build'