美文网首页
内存优化

内存优化

作者: xyzkaye | 来源:发表于2023-02-23 21:13 被阅读0次

Java虚拟机

Java虛拟机是一台“抽象的计算机”,它拥有自己的处理器,堆栈,寄存器以及相应的指令系统;Java虚拟机屏蔽了与具体操作系统相关的平台信息,使得Java程序只需要生成在该虛拟机上运行的目标代码,就可以在多平台上运行;虽然叫Java虚拟机,但在它之上运行的语言不仅有Java, Kotlin, Groovy,Scala等都可以运行;

Java虚拟机执行流程

      编译时环境    =====传递class文件=====》 运行时环境
      
      Activity.java                       Activity.class
             ↓                                   ↓
       Java编译器                            Java虚拟机
             ↓
       Activity.class
JVM运行时数据区.png

线程独占:每个线程都会有它独立的空间。随线程生命周期而创建和销毁(Java虚拟机栈,本地方法栈,程序计数器)
线程共享:所有线程能访问这块内存数据,随虚拟机或者GC而创建和销毁 (方法区,Java堆)

方法区

JVM用来存储加载的类信息、常量、静态变量、编译后的代码等数据
虚拟机规范中这是一个逻辑区划。具体实现根据不同虚拟机来实现。
如:oracle的HotSpot在 java7中方法区放在永久代,java8放在元数据空间,并且通过GC机制对这个区域进行管理

Java堆

堆内存还可以细分为:老年代、新生代 (Eden、From Survivor、To Survivor )
JVM启动时创建,存放对象的实例。垃圾回收器主要就是管理堆内存。
如果满了,就会出现OutOfMemroyError。

虛拟机栈

虛拟机栈,每个线程都在这个空间有一个私有的空间。
线程栈由多个栈帧(Stack Fframe)组成。
一个线程会执行一个或多个方法,一个方法对应一个栈帧
栈帧内容包含:局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。
栈内存默认最大是1M,超出则抛出StackOverflowError。

本地方法栈

和虛拟机栈功能类似,虚拟机栈是为虚拟机执行JAVA方法而准备的,本地方法
栈式为虚拟机使用Native本地方法而准备的。
虚拟机规范没有规定具体的实现,由不同的虚拟机厂商去实现。
HotSpot虚拟机中虚拟机栈和本地方法栈的实现方式是一样的。同样,超出大小以后也会抛出StackOverflowError。

程序计数器

程序计数器 (Program Counter Register)记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器值为空。
每个线程都在这个空间有一个私有的空间,占用内存空间很少。
CPU同一时间,只会执行一条线程中的指令。JVM多线程会轮流切换并分配CPU执行时间的方式。为了线程切换后,需要通过程序计数器,来恢复正确的执行位置。

执行引擎+本地库接口+本地方法库 是用来实现跨平台操作的,针对不同的系统做出不同的操作实现,并向上层提供接口可以调用,从而实现跨平台。

垃圾回收(GC)

强/软/弱/虚引用

强引用:
当新建的对象为强引用时,垃圾回收器绝对不会回收它。宁愿抛出OutofMemoryError异常,让程序异常终止也不会回收;
软引用:
当新建的对象为软引用时,当内存不够时,回收器就会回收这些对象,如果回收后还是没有足够的内存,拋出OutOfMemoryError异常;
弱引用:
当新建的对象为弱引用时,垃圾回收器不会管当前内存是否足够,都会回收它的内存;
虚引用:
虚引用跟其他引用都不同,如果一个对象仅持有虚引用在任何时候都可能被GC回收,只是当它被回收时会收到一个系统通知;

垃圾标记算法--引用计数法

引用计数算法:
每个对象都有一个引用计数器,当对象每被引用一次时就加1,引用失效时就减1。当计数为0时则将该对象设置为可回收的 “垃圾对象”;

垃圾标记算法--跟搜索算法

这个算法的基本思想是通过一系列称为“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链(即GC Roots到对象不可达)时,则证明此对象是不可用的。

垃圾标记算法--引用计数法

标记-清除算法:
顾名思义,请用根搜索算法标记可被回收的对象,之后将被标记为 “垃圾”的对象进行回收;

垃圾标记算法--复制算法

复制算法:
先把内存一分为二,每次只使用其中一个区域,垃圾收集时,将存活的对象全部拷贝到另外一个区域,然后对之前的区域进行全部回收;

垃圾标记算法--标记-压缩算法

标记-压缩算法:
在标记可回收的对象后,将所有的存活的对象压缩到内存的一端,让他们排在一起,然后对边界以外的内存进行回收;

垃圾标记算法--分代收集算法

分代收集算法:

Java堆中存在的对象生命周期有较大差别,大部分生命周期很短,有的很长,甚至与应用程序或者Java虛拟机生命周期一样。因为分代算法就是根据对象的生命周期长短将放到不同的区域;

内存泄漏/溢出

内存泄漏:一个不再被程序使用的对象或变量依旧存活在内存中无法被回收;
常见的内存泄漏原因及解决方法标题

内存溢出:当程序申请内存时,没有足够的内存供程序使用;
比较小的内存泄漏并不会有太大的影响,但内存泄漏多了,占用的内存空问就更大,序正常需要申请使用的内存则会相应减少;

内存抖动

内存抖动通常是指在短时间内发生了多次内存的分配和释放,主要原因则是短时间内频繁的创建对象,为了应对这种情况,虚拟机会频繁的触发GC操作,当GC进行时,其他线程会被挂起等待GC的完成,频繁GC,比如UI在绘制时会超过16ms一帧,导致画面卡顿等;

内存优化

  1. 工具使用
  1. 优化点
  • 避免在for循环里分配对象占用内存
  • 自定义View的onDraw方法避免执行复杂的方法与创建对象
  • 采用对象池模型解决频繁创建与销毀
  • 对bitmap做缩放,重用bitmap
  1. 优化点
  • 配置LargeHeap熟悉
  • 在onTrimMemory进行处理
  • 使用松散数组 SparseArray,ArrayMap

相关文章

网友评论

      本文标题:内存优化

      本文链接:https://www.haomeiwen.com/subject/bcpakdtx.html