You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环生成大JSON遇dalvikvm-heap堆增长报错(仅华为设备)

Why Does Heap Growth (Frag Case) Happen When Building Large JSON in a Loop?

Hey there! Let's dig into why you're seeing that I/dalvikvm-heap: Grow heap (frag case)... log on your Huawei device, and how to fix the underlying memory issues.

Root Causes of the Heap Growth

Let's break down what's triggering this heap expansion, especially why it only shows up on Huawei devices:

  • Unnecessary Temporary Object Creation
    Looking at your setItem_M0 method:

    JSONArray jA1 = new JSONArray(); // This is totally redundant!
    JSONObject jO1 = new JSONObject();
    JSONObject jO2 = new JSONObject();
    try {
        jA1 = obj.getJSONArray("M0"); // You overwrite the new JSONArray immediately
        // ... rest of code
    }
    

    Every loop iteration creates 3 new objects, but jA1 gets discarded right away. Multiply that by 10,000 iterations, and you're generating 30,000 short-lived objects that pile up in memory until GC runs. This causes heap fragmentation—small unused memory blocks can't hold new allocations, forcing the VM to grow the heap.

  • Device-Specific Heap Configuration
    Different Android OEMs tweak Dalvik/ART heap settings. Your Samsung devices likely have a larger initial heap size or more aggressive GC triggers, so they can handle the temporary objects without needing to expand the heap. Huawei's default heap parameters are stricter (smaller initial size, slower GC), so the fragmentation hits the threshold for heap growth faster.

  • JSONArray Repeated Resizing
    When you create the M0 JSONArray with new JSONArray() (no initial capacity), it starts with a small default size. Every time you add an item beyond its current capacity, it has to resize (allocate a new larger array and copy elements over). This adds more memory overhead and fragmentation.

Fixes to Reduce Heap Usage & Fragmentation

Here are concrete code optimizations to eliminate the heap growth issue:

1. Eliminate Redundant Object Creation

Rewrite the setItem_M0 method to stop creating unnecessary objects:

public void setItem_M0(A_DataClass Item) {
    JSONObject jO1 = new JSONObject();
    JSONObject jO2 = new JSONObject();
    try {
        // Get the existing JSONArray directly—no need to create a new one first
        JSONArray jA1 = obj.getJSONArray("M0");
        jO1.put("a", Item.getA());
        jO2.put("a", Item.getB());
        jO1.put("b", jO2);
        jA1.put(jO1);
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

Even better: If you want to minimize object creation further, initialize jO1 and jO2 once as instance variables in JSON_Functions_PRD, and reset their values with remove() or put() each time instead of creating new objects.

2. Pre-Allocate JSONArray Capacity

When creating the M0 array, specify the exact number of items you'll add (since you know count = 10000):

public void CreateMenu_SMS_Naked() {
    // Pass the expected item count to avoid repeated resizing
    JSONArray jA1 = new JSONArray(10000);
    try {
        obj.put("M0", jA1);
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

This tells the JSONArray to allocate enough space upfront, eliminating expensive resize operations and reducing fragmentation.

3. Reuse Your Data Class Instance

You're already doing this correctly (using the same mDataClass for all iterations), but just confirming—this is a good practice that avoids creating 10,000 extra A_DataClass objects.

4. Batch Processing (For Extreme Cases)

If you ever need to handle even larger datasets, split the loop into batches and hint to the GC to run after each batch:

int count = 10000;
int batchSize = 1000;
for (int i = 0; i < count; i++) {
    mDataClass.setA("A1");
    mDataClass.setB("B1");
    mJSONF_Test.setItem_M0(mDataClass);
    
    if ((i + 1) % batchSize == 0) {
        // Hint to GC to clean up temporary objects
        System.gc();
    }
}

Note: System.gc() is just a hint—don't rely on it for regular cleanup, but it can help in large batch operations.

Why Huawei vs. Samsung?

As mentioned earlier, OEMs adjust VM settings. Samsung likely configures a larger initial heap (dalvik.vm.heapsize) or more frequent GC runs, so their devices can absorb the temporary object churn without needing to grow the heap. Huawei's default settings are more memory-efficient (smaller initial heap) but less forgiving of inefficient object creation.


内容的提问来源于stack exchange,提问作者AndroidHV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:59:16