Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách đặt giới hạn heap watch (setWatchHeapLimit) trên Android

Giới thiệu

Bài viết hướng dẫn sử dụng ActivityManager.setWatchHeapLimit() để đặt ngưỡng theo dõi heap size. Khi heap của process vượt ngưỡng này, hệ thống sẽ ghi log cảnh báo. Dùng cho debug/profiling memory.

Các bước thực hiện

Bước 1: Tạo project mới

Android Studio → File → New Project → Empty Activity.

Bước 2: Giao diện (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="16dp">

    <TextView
        android:id="@+id/tvStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Heap watch limit set"
        android:textSize="18sp" />

</LinearLayout>

Bước 3: Code (MainActivity.kt)

package com.example.setheapwatch

import android.app.ActivityManager
import android.content.Context
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

        // Đặt giới hạn heap watch: 4 MB (4096 KB = 4,194,304 bytes)
        // Tham số là BYTES
        val limitBytes = 4 * 1024 * 1024 // 4MB
        activityManager.setWatchHeapLimit(limitBytes)

        tvStatus.text = "Đã đặt heap watch limit: ${formatBytes(limitBytes)}"
    }

    private fun formatBytes(bytes: Long): String {
        return when {
            bytes >= 1024 * 1024 -> "${bytes / (1024 * 1024)} MB"
            bytes >= 1024 -> "${bytes / 1024} KB"
            else -> "$bytes B"
        }
    }
}

Giải thích

  • setWatchHeapLimit(bytes: Long): Thiết lập ngưỡng heap (bytes). Khi heap allocated > ngưỡng, hệ thống log warning.
  • Đơn vị tham số: **Bytes** (không phải KB/MB).
  • clearWatchHeapLimit(): Xóa ngưỡng đã đặt.
  • Chủ yếu dùng trong **development/debugging** để phát hiện memory leak sớm.

⚠️ Lưu ý QUAN TRỌNG: Quyền hạn chế

App thông thường KHÔNG THỂ sử dụng API này.

  • Cần quyền android.permission.SET_ACTIVITY_WATCHER (protectionLevel: signature|privileged).
  • Chỉ **system apps** (pre-installed, signed với platform key) hoặc **root** mới được cấp quyền này.
  • App user-installed sẽ bị SecurityException hoặc no-op silently.

Cách debug memory cho app thường (Thay thế)

1. Android Studio Profiler (Khuyên dùng nhất)

View → Tool Windows → Profiler → Memory tab. Theo dõi realtime: Java heap, Native heap, Graphics, Stack, Code, Others. Capture heap dump, record allocations.

2. Debug.MemoryInfo (App process memory)

val debugInfo = Debug.MemoryInfo()
Debug.getMemoryInfo(debugInfo)
Log.d("Memory", "Native Heap: ${debugInfo.nativeHeapAllocatedSize / 1024} KB")
Log.d("Memory", "Dalvik Heap: ${debugInfo.dalvikHeapAllocatedSize / 1024} KB")

3. ActivityManager.getProcessMemoryInfo()

val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val pids = intArrayOf(android.os.Process.myPid())
val infos = am.getProcessMemoryInfo(pids)
val pss = infos[0].totalPss // KB - Proportional Set Size (chuẩn đo memory thực)

4. LeakCanary (Library phát hiện leak tự động)

// build.gradle
debugImplementation "com.squareup.leakcanary:leakcanary-android:2.12"
// Tự động báo leak trong debug build

5. onTrimMemory() callback

override fun onTrimMemory(level: Int) {
    super.onTrimMemory(level)
    when (level) {
        ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> { /* Clear UI caches */ }
        ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW -> { /* Reduce memory */ }
        ComponentCallbacks2.TRIM_MEMORY_BACKGROUND -> { /* Clear non-essential */ }
    }
}