安卓实用知识Android开发Android知识

Android内存优化(一):Java内存区域

2017-02-20  本文已影响265人  C6C

导语

最近一段时间需要对项目的内存进行优化,因为项目比较老,代码经过很多手,导致应用在使用过程中有较为严重的内存泄漏,在某些情况下还会出现OOM,简直是不能忍,所以简单记录一下从入门到放弃的过程,就当做是学习和总结。

JAVA运行时内存区域

Java虚拟机有一套内存自动管理的机制,所以程序员不需要也不能手动的alloc内存,这在很大程度上避免了内存泄漏的发生,但是不能百分百的避免。

在执行程序的时候会对它管理的内存进行划分,在不同的区域分配不同的工作,下图中展示了运行时各区域的基本结构,主要分为线程私有和共享两类:

1.1程序计数器

程序计数器是线程私有的,且是内存分区里头唯一一个不会造成OOM异常的一个内存区域。

它的作用是虚拟机字节码指令执行过程的管理者,通过计数器的值就可以控制下一条需要执行的指令字节码,它记录的是字节码指令的地址,由于Java虚拟机可以执行多线程,而每个处理器在每个时刻都只会执行一条线程,为了线程切换过程中保证字节码指令的稳定,每一条线程都会持有一个独立的计数器。需要说明的是,以上我们针对的是Java方法,如果虚拟机执行的是Native方法的话,计数器的值会为0。

1.2虚拟机栈

Java虚拟机栈是线程私有的,它负责Java方法执行过程中的入栈、弹栈,它可能会造成两种异常,StackOverFlowError与OutOfMemoryError,就是栈溢出与内存溢出。

我们经常会提到栈内存,这个栈内存指的就是虚拟机栈,虚拟机栈是的构成元素是栈帧,每个栈帧包含了局部变量表,操作数栈,动态连接,方法返回地址和一些额外信息,一个方法对应一个栈帧,方法从开始调用到执行结束的过程,就是一个栈帧在虚拟机栈中入栈到弹栈的过程。


大概讲一下图中的栈帧各组成结构作用

1.3本地方法栈

本地方法栈与虚拟机栈功能基本一样,是线程私有的,两者的主要区别在于它负责Native方法执行过程中的入栈、弹栈,而虚拟机栈负责Java方法,它也可能会造成两种异常,StackOverFlowError与OutOfMemoryError,就是栈溢出与内存溢出。

1.4堆

平时程序猿所讨论的堆栈,栈指的是虚拟机栈,而这个堆就是这里讲到的Java堆,它是线程共享的,基本上所有的对象和数组都是在堆上分配内存的。它可能会造成OutOfMemoryError异常。
OOM异常一般是堆中内存不足造成的,由于对象不能或者未及时释放,导致对象一直占用堆中的内存,这会造成内存泄漏,当积累到一定程度,即堆内存不够用的时候虚拟机就会抛出OOM异常。
Java堆也称为"GC堆",对象的创建可以说是程序中最为频繁的现象,Java虚拟机会自动管理Java堆中的内存,在内存不够用的时候虚拟机会启动垃圾收集器进行垃圾回收操作释放一部分没有被引用的对象。后面有时间的话可以讲一下垃圾回收相关的知识。

1.5方法区

方法区跟堆一样,属于线程共享,当内存不足时会抛OutOfMemoryError异常。方法区逻辑上是堆的一部分,但是又会和堆区分开来,所以又称为非堆。
在我们的开发中,有时会把方法区称为永久代,用于存储一些类信息、常量、静态变量等,从永久代这个称谓中就可以看出在方法区中的变量存活时间比较久,因为这个区域很少会发生垃圾收集的行为,但是并非数据进入方法区后就会永久存在,方法区中的常量池是存在被垃圾回收的可能的。

上一篇下一篇

猜你喜欢

热点阅读