文章用来记录及分享本人对安卓程序中内存使用的个人见解,如有不同见解 不吝赐教。
先简单浏览下面代码,看看对它们是否熟悉👇
val activityManager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
// Java 堆内存信息
val runtime = Runtime.getRuntime()
val usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024
val maxMemory = runtime.maxMemory() / 1024 / 1024
//todo Native内存和Java(Dalvik/ART)内存是分开的
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
// 获取系统内存信息
// 获取应用最大可使用内存,标准模式和大内存模式
//应用在Dalvik/ART虚拟机中可以分配的最大内存。
val memoryClassMb = activityManager.memoryClass
//用于那些需要更多内存的应用,表示在大内存设备上应用可以使用的内存预算。
val largeMemoryClassMb = activityManager.largeMemoryClass
//系统总内存
val totalMemoryMb = memoryInfo.totalMem / 1024 / 1024
//系统可用内存
val availMemoryMb = memoryInfo.availMem / 1024 / 1024
//系统已用内存
val usedMemoryMb = totalMemoryMb - availMemoryMb
val lowMemory = memoryInfo.lowMemory
Log.d(TAG, "系统总内存: $totalMemoryMb MB \n" +
"系统可用内存: $availMemoryMb MB\n" +
"系统已用内存: $usedMemoryMb MB\n" +
"应用最大可使用内存 (标准模式): ${memoryClassMb}MB\n" +
"应用最大可使用内存 (大内存模式): ${largeMemoryClassMb}MB")
val debugMemoryInfo : Debug.MemoryInfo = Debug.MemoryInfo()
Debug.getMemoryInfo(debugMemoryInfo)
//当前程序的总内存使用量(以 MB 为单位)(包括 Java 堆、Native 堆以及其他内存使用,整个进程的总内存使用)
val totalPssMb = debugMemoryInfo.totalPss.toLong() / 1024
// 当前进程在 native 层可用的总堆内存大小(以 MB 为单位)
val nativeHeapSize: Long = Debug.getNativeHeapSize() / 1024 / 1024
//当进程中native层中已使用堆内存(以 MB 为单位)
val useNative : Long = Debug.getNativeHeapAllocatedSize() / 1024 / 1024
//当前进程中native层中剩余的堆内存(以 MB 为单位)
val freeNative = Debug.getNativeHeapFreeSize() / 1024 / 1024
// 计算当前应用剩余可用的内存
val maxMemoryClassMb = if (largeMemoryClassMb > memoryClassMb) largeMemoryClassMb else memoryClassMb
val remainingMemoryMb = maxMemoryClassMb - totalPssMb
// 检查是否接近内存上限
val isMemoryLow = usedMemory > maxMemory * 0.8 || useNative > nativeHeapSize * 0.8 || lowMemory
在开发安卓应用时,内存管理一直是一个关键的考虑因素。良好的内存管理不仅可以提高应用的性能,还能避免内存泄漏和崩溃,由于项目所需,特来恶补相关知识。
1. Java 堆内存
Java 堆内存是 JVM 分配给应用的内存,主要用于分配对象。通过 Runtime.getRuntime() 可以获取和管理 JVM 的堆内存信息。
val runtime = Runtime.getRuntime()
val usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024
val maxMemory = runtime.maxMemory() / 1024 / 1024
- 已用内存(usedMemory):当前应用已经使用的堆内存。
- 最大内存(maxMemory):JVM 能够使用的最大内存。
注意事项
- 避免内存泄漏:确保不再使用的对象能及时被垃圾回收,避免持有不必要的引用。
- 合理分配内存:尽量减少大对象的使用,优化数据结构以节省内存。
2. 系统内存
系统内存是整个设备的内存,包括所有运行的应用和系统服务。通过 ActivityManager
可以获取设备的系统内存信息。
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
val totalMemoryMb = memoryInfo.totalMem / 1024 / 1024
val availMemoryMb = memoryInfo.availMem / 1024 / 1024
val usedMemoryMb = totalMemoryMb - availMemoryMb
val lowMemory = memoryInfo.lowMemory
- 系统总内存(totalMemoryMb):设备的总内存。
- 系统可用内存(availMemoryMb):设备当前可用的内存。
- 系统已用内存(usedMemoryMb):设备当前已使用的内存。
- 低内存标志(lowMemory):系统是否处于低内存状态。
注意事项
- 在低内存状态下,系统可能会回收后台应用的内存以确保前台应用正常运行。开发者应适当释放资源,避免应用被系统强制终止。
3. 应用内存配额
安卓系统对每个应用分配了内存配额,标准模式和大内存模式下的内存配额有所不同。
val memoryClassMb = activityManager.memoryClass
val largeMemoryClassMb = activityManager.largeMemoryClass
- 标准模式内存配额(memoryClassMb):应用在标准模式下最大可使用的内存。
- 大内存模式内存配额(largeMemoryClassMb):应用在大内存模式下最大可使用的内存。
注意事项
- 合理选择内存模式:对于需要大量内存的应用,可以申请大内存模式,但要确保设备支持。
4. 进程内存信息
通过 Debug.MemoryInfo 可以获取当前进程的内存使用情况,包括 Java 堆、Native 堆以及其他类型的内存使用。
val debugMemoryInfo : Debug.MemoryInfo = Debug.MemoryInfo()
Debug.getMemoryInfo(debugMemoryInfo)
val totalPssMb = debugMemoryInfo.totalPss.toLong() / 1024
- 总 PSS 内存(totalPssMb):当前应用进程的总内存使用量,一般程序使用内存情况就看这个数据。
5. Native 层内存
除了 Java 堆,应用还会使用 Native 层的内存。通过 Debug 类可以获取 Native 堆内存信息。
val nativeHeapSize: Long = Debug.getNativeHeapSize() / 1024 / 1024
val useNative : Long = Debug.getNativeHeapAllocatedSize() / 1024 / 1024
val freeNative = Debug.getNativeHeapFreeSize() / 1024 / 1024
- Native 堆大小(nativeHeapSize):当前进程在 Native 层可用的总堆内存。
- 已使用的 Native 内存(useNative):当前进程中 Native 层已使用的堆内存。
- 剩余的 Native 内存(freeNative):当前进程中 Native 层剩余的堆内存。
注意事项
- 避免 Native 内存泄漏:使用 C/C++ 编写的代码要特别注意内存管理,确保分配的内存在使用后能及时释放。
先写到这,后续深入了解后再继续补充
下班,端午快乐~