Android中的内存

Android系统给每个应用分配的内存大小都是有限的,那什么是内存呢?


内存包括:寄存器,栈(Stack)和堆(Heap),静态存储区域,常量池.


首先从我比较熟悉的堆和栈说起吧:




看图:这些从网上也是可以直接搜索出来的,


对象实例数据
---》实际上是保存对象实例的属性,属性的类型和对象本身的类型标记等,但是不保存实例的方法。实例的方法是属于数据指令,是保存在Stack里面,也就是上面表格里面的类方法。
我的理解:当我们new一个对象的时候,该对象的属性都是保存在堆(Head)中的,而方法保存到栈(Stack)中






---》对象实例在Heap中分配好以后,会在stack中保存一个4字节的Heap内存地址,用来查找对象的实例。因为在Stack里面会用到Heap的实例,特别是调用实例的时候需要传入一个this指针。
我的理解:有了解过指针的应该都很容易看懂,就是new一个对象的时候,对象在保存在堆中的(属性等是保存到堆中的(head),只有方法是保存在栈中的(Stack)),但是当我们要调用这个实例的时候是需要this,上下文的。






方法内部变量
---》类方法的内部变量分为两种情况:简单类型保存在Stack中;对象类型在Stack中保存地址,在Heap 中保存值。
我的理解:简单类型:int ,float,double,long等,直接保存到栈中(Stack),对象类型Integer,Double,Float,和一些自定义的类型




非静态方法和静态方法


----》非静态方法有一个隐含的传入参数,这个参数是dalvik虚拟机传进去的,这个隐含参数就是对象实例在Stack中的地址指针。因此非静态方法(在Stack中的指令代码)总是可以找到自己的专用数据(在Heap 中的对象属性值)。当然非静态方法也必须获得该隐含参数,因此非静态方法在调用前,必须先new一个对象实例,获得Stack中的地址指针,否则dalvik虚拟机将无法将隐含参数传给非静态方法。 
我的理解:我们在调用一个方法的时候,总是要实例化一个对象,然后通过:对象点方法来调用的(Object.Method)


--->静态方法没有隐含参数,因此也不需要new对象,只要class文件被ClassLoader load进入JVM的Stack,该静态方法即可被调用。所以我们可以直接使用类名调用类的方法。当然此时静态方法是存取不到Heap 中的对象属性的。
我的理解:java文件被JVM加载的时候是进入到栈的(Stack),所以可以直接通过类名来调用静态方法






静态属性和动态属性


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




小结


  Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。


  堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。


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


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






栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)
栈用于存放基本类型的数据和对象的引用,但对象的本身不存放在栈中,而是存放在堆中。




堆:堆内存用来存放由new创建的的对象和数组。在堆中分配的内存,由java的虚拟机的垃圾自动回收器GC来管理




寄存器:速度最快的存储场所,因为寄存器位于处理器内部,在程序中无法控制。


 
静态存储区域:静态存储区域存放应用程序运行时一直存在的数据,Java在内存中专门划分一个静态存储区域来管理一些特殊的数据变量如静态的数据变量




常量池:Java虚拟机必须为每个被装载的类型维护一个常量池,常量池就是该类型所用到的常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型,字段和方法的符号引用


代码获取堆大少,所谓的内存分析,正是分析Heap中的内存状态



        ActivityManager  activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        int size = activityManager.getLargeMemoryClass();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值