jvm<二> 内存管理
java虚拟机回收
gc roots 查找机制
gc roots对象可达, 不会被释放
1.虚拟机栈本地变量表引用的对象
2.方法区中静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈中jni
另外,(Android)可以确认的是:
1.主线程的messagequeue,成员变量中的匿名内部类,除非发空消息(null),要不然,依然泄漏
2.主线程的messagequeue, 调用静态内部类,如果调用了外部类的成员变量,依然泄漏。
3.子线程,操作主线程的view,或者成员变量会泄漏。
运行时数据区域
1.方法区
线程共享
类信息,常量,静态变量 (hotspot放弃永久代逐步改为 native memory实现) ,类型卸载,常量池回收(1.7移除了放在永久代的字符串常量池)
运行时常量池:存放编译期时生成的字面量和符号引用
2.堆
线程共享
3.虚拟机栈
线程独立
广义:局部变量表,生命周期同线程 ,为虚拟机执行java方法
4.本地方法栈
线程独立
为虚拟机执行native方法
5.程序计数器
线程独立
直接内存,非运行时内存(direct memory)
直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现。
JDK1.4加的NIO中,ByteBuffer有个方法是allocateDirect(int capacity) ,这是一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在 Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和 Native堆中来回复制数据。
显然,本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,则肯定还是会受到本机总内存(包括RAM及SWAP区或者分页文件)的大小及处理器寻址空间的限制。服务器管理员配置虚拟机参数时,一般会根据实际内存设置-Xmx等参数信息,但经常会忽略掉直接内存,使得各个内存区域的总和大于物理内存限制(包括物理上的和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。
====================安卓泄漏
1.静态类和匿名内部类持有context的引用时,会导致内存泄漏
2.handler,需要在destroy中remove
3.子线程任务要在destroy前暂停掉。
4.输入法<=23 也会泄漏,
5.地图也尽量用applocation context
6.尽量用安卓applocation context去掉用服务等。