设为首页 加入收藏

TOP

Android 内存管理(一)
2023-08-26 21:10:24 】 浏览:362
Tags:Android 管理

一、需求

        我司存在内存为1G RAM的设备,属于低内存设备,经常会出现内存很紧张的场景,也容易因此导致一系列七七八八的边际问题,故有必要了解Android系统的内存相关知识:

  1. 了解内存的分配、回收方式
  2. 了解OOM、LMK的相关机制
  3. 了解Android系统内存相关调试方式
  4. 了解Android系统的性能优化方案

二、环境

  1. JDK 1.8
  2. Android 10

三、JVM

        JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一个虚构出来的计算机,有着自己完善的硬件架构,如处理器、堆栈等。

3.1 编译&执行过程

        Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
        Java文件必须先通过一个叫javac的编译器,将代码编译成class文件,然后通过JVM把class文件解释成各个平台可以识别的机器码,最终实现跨平台运行代码。

3.2 JVM内存模型

3.2.1 方法区

        方法区是《Java虚拟机规范》中规定的一个内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。方法区是一个规范,它的实现取决于不同的虚拟机:

  1. 在Java8之前,HotSpot虚拟机使用 永久代 来实现方法区。
  1. 而Java8之后,HotSpot虚拟机使用 元空间 来实现方法区。
        元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存;永久代在虚拟机中。

        方法区存储的信息如下:

名称 内容
类型信息 (1)是类class、接口interface、枚举enum、注解annotation中哪一种
(2)完整有效名称(包名.类名)
(3)直接父类的完整名称(接口和java.lang.Object没有父类)
(4)类型的修饰符(public、abstract、final等)
(5)类型直接接口的有序列表(实现的接口构成列表)
域(Field、属性)信息 (1)保存类型所有域(属性)的相关信息和声明顺序
(2)相关信息包含:域名称、域类型、域修饰符(public、private、protected、static、final、volatile、transient等)
方法(method)信息:按顺序保存 (1)方法名称
(2)返回类型(含Void)
(3)方法参数和类型(按顺序)
(4)方法的修饰符(public、private、protected、static、final、synchronized、native、abstract)
(5)方法的字节码、操作数栈、局部变量表及其大小(abstract和native方法除外)
(6)异常表abstract和native方法除外),每个异常处理开始、结束位置,代码处理在程序计数器中的偏移地址,被捕获的异常类的常量池索引等
Non-final类变量:(static修饰的变量,静态变量) (1)逻辑上是类数据一部分
(2)在类的加载过程中链接的准备阶段设置默认初始值,初始化阶段赋予真实值
(3)类变量(non-final)被所有实例共享,没有实例化类对象也可访问,(全局常量,static和final一起修饰)
(4)与final修饰的类变量不同,每个全局常量在编译时就分配了
Class文件常量池 (1)一个有效的字节码文件除了包含类的版本信息、字段、方法以及接口描述信息外,还包含一个常量池表。常量池表中包含字面量、域和方法的符号引用。
(2)字面量就是int i=5;String=”Hello World!”中的5和”Hello World!”
(3)一个JAVA源原文件中的类、接口,编译后生成字节码文件,Java中的字节码需要数据,但是这些数据很多很大,不能直接存到内存中,可以将其存到常量池中,字节码中包含了指向常量池的引用。
(4)常量池中包含:数量值、字符串引用、类引用、字段引用、方法引用
运行时常量池 (1)运行时常量池是方法区的一部分
(2)常量池表示Class中的一部分,用于存放编译器生成的各种字面量和符号引用,在加载类和接口到虚拟机后,就创建相应的运行时常量池
(3)JVM为每个加载的类或接口维护一个运行时常量池,池中数据类似数组项,通过索引访问
(4)运行时常量池中含多种不同常量,包含编译器就明确的数值字面量,也包含运行期的方法或者字段引用,此时不再是常量池中的符号地址,而是真实地址。
(5)运行时常量池,相对于Class文件中的常量池,还有一个特征就是具备动态性,可以动态添加数据到运行时常量池
(6)当创建运行时常量池时,如果所需内存空间大于方法区能提供的最大值,那么JVM抛出OutOfMemoryError异常

3.2.2 堆

        堆是java内存管理中最大的一块内存,也是所有线程共享的一块内存,在虚拟机启动时创建。堆中主要存放的是对象实例、数组。几乎所有的对象实例、数组都在这一块内存中分配。
        堆也是GC垃圾回收的主要区域。垃圾回收现在主要采取的是分代垃圾回收算法。为了方便垃圾回收,java堆还进行了细分:新生代(YoungGen)、和老年代(oldGen),默认占比为:1:2;其中新生代还可以划分为Eden空间、survivor0空间、survivor1空间,默认占比为:8:1:1;

对象内存分配过程如下:
        1.new一个对象value,value先放于新生代->Eden区;
        2.当Eden区空间填满后,我们需要再创建value2对象,JVM会对Eden区继续垃圾回收(Minor GC);
        3.Eden区触发GC后,Eden区会被清空,同时Eden区幸存对象会移动到S0幸存区。此时,Eden区和S1区未存放对象;
  &nb

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/10/10
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Android 调试桥 (adb) 使用教程/.. 下一篇免费发布应用托管平台

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目