Android内存管理

2023-12-11  本文已影响0人  _汉堡_

1、先了解Android运行时环境
在Android平台上,应用程序通常是用Java或者kotlin等高级语言编写的,然后编译成特定于Android的字节码(.dex格式的字节码),这些字节码需要通过一个运行时环境来执行。这个运行时环境在早期版本的Android中是Dalvik虚拟机,而在Android 4.4(KitKat)以及之后的版本中则是Android Runtime(ART)。

先讲应用程序的执行过程
Dalvik和ART中略有不同:

Dalvik:应用程序被编译成.dex格式的Dalvik字节码,然后在设备上运行时,Dalvik虚拟机使用JIT编译器将这些字节码转换为机器码,并执行它们。

ART:应用程序同样被编译成.dex格式的字节码。但是,在应用安装到设备上时,ART会使用AOT编译器将这些字节码预编译成机器码。安装完成后,应用程序代码就是可直接执行的机器码,无需在每次运行时重新编译。所以

一个是运行时再编译(每一次都要编译),一个是安装的时候编译后续直接执行 这就是JIT和AOT
JIT (Just-In-Time) 编译
"JIT"代表Just-In-Time编译,它是一种与AOT相对的编译技术,程序代码是在程序运行时即时编译成本地代码的。这种方式的好处是,编译器可以根据程序运行时的实际性能情况来优化代码,可能在某些情况下提供更好的性能。另外,JIT编译也减少了应用程序的初始安装大小,因为它不需要存储预编译的本地代码。

AOT (Ahead-of-Time) 编译
"AOT"代表Ahead-of-Time编译,这是一种编译技术,其中程序代码在应用安装时(或者在某些情况下是第一次运行之前)就被编译成本地机器代码。AOT编译的优势在于,由于代码已经是编译好的,所以应用程序可以更快地启动和运行,因为它减少了在应用程序运行时动态编译的需求和开销。

而ART就是使用AOT进行编译的

2、内存分配
开发者最常打交道的就是 java/kotlin层和navite层
其他的还有(系统服务层,硬件抽象层,Linux内核层,驱动层)这些系统层面或硬件驱动开发者关注的点
怎么理解这(Java/Kotlin层)(Navite层)这两层呢?

 java/kotlin层:
在Android开发中,Java和Kotlin是两种主流的高级编程语言,它们都运行在虚拟机上,Java 运行在 Java 虚拟机 (JVM) 上,而 Kotlin 也是完全兼容 JVM 的。它们被广泛用于编写 Android 应用。

对象创建:
Java:
对象的创建通过使用new关键字,这会在堆内存中分配空间给新对象。
Kotlin:在Kotlin中,可以直接调用构造函数来创建对象,不需要new关键字,但在底层,这同样会在堆上分配内存

每new一个新对象的时候 内存就会在堆内存上为对象分配一个内存
分配内存-创建对象-返回引用
如果创建的时候 内存不够/满了

在Java中,
会先尝试运行垃圾回收来回收未使用的对象,以便为新对象腾出空间,还是不够用的情况下,
就会抛出异常OutOfMemoryError,表明JVM没有足够的内存来为新对象分配空间

每个应用程序内部通常会区分堆内存(heap memory)和栈内存(stack memory):

堆内存用于动态分配的内存,其生命周期不固定,需要通过应用程序代码或垃圾回收机制进行管理。

栈内存用于存储函数调用的局部变量和管理调用栈,其内存分配和回收是自动进行的,生命周期通常随着函数的调用和返回而变化。

堆内存(Heap Memory):
什么是堆内存?
动态分配的内存就是堆内存(至少在Java和kotlin里总是这么指的)
堆内存用于在运行时动态分配内存

堆内存的生命周期
在没有垃圾回收器的语言中(C/C++)需要显式地申请和释放
但Java/kotlin 有垃圾回收器,所以对象的生命周期会由垃圾回收器控制,当没有任何引用指向一个对象的时候,GC会认为这个对象不再需要,并在合适的时候将其回收
堆内存中的对象不会自动销毁,它们的生命周期不受单个函数调用的限制,可以跨越函数、线程甚至应用程序的范围。

在多线程环境中,堆内存是被所有线程共享的,就是说所有的线程都能访问堆内存上的对象,所以要注意线程安全。

方法区(Method Area):
是堆的一个逻辑部份
它被所有线程共享。是一片固定大小的区域
方法区在JVM启动时创建,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
在java8之前JVM用一块名为永久代的内存区域来实现方法区

元空间(MetaSpace):
在本地内存的一个存放java8之前的永久代的空间,代替永久代储存类的信息,静态变量,字符串常量池,
取代原因:不再固定大小,动态分配大小,系统越大就能分配越多,不受固定大小影响,不放在堆内存里面.

栈内存(Stack Memoy):
什么是栈内存?
栈是线程私有的内存区域。
每个线程创建的时候都会生成自己的栈
栈用于储存方法调用的栈帧
什么是栈帧?
简而言之,栈帧是方法执行的基本单元,包含了所有执行方法需要的信息。

上一篇 下一篇

猜你喜欢

热点阅读