Android 踏雷日記(1)String Out Of Memory
来源:互联网 发布:赛诺手机数据 编辑:程序博客网 时间:2024/06/07 18:38
今天在開發字典查詢 App 的時候發生了檔案讀出來存成 buffer 後, 再轉成 String 的過程中發生 Out Of Memory, 一直在百思不解的情況下上社群問了解法, 得到的結果是在 AndroidManifast.xml
的 <applicaton>
標籤加入 android:largeHeap="true"
屬性解決, 可是有些手機卻不用就能夠正常執行, 到底是發生了什麼原因呢?讓我們來還原現場吧!
還原現場步驟:
- 環境介紹
- 環境:Android
- 版本:4.3
- 檔案格式:json
- 測試機器:genymotion (Nexus s)
- 測試檔案:https://github.com/weitsai/hahadict/raw/master/dict.json.bz2
- 把檔案放到 Assess 裡面
- 在 Activity 把這個檔案讀出來並轉成 String12345678910
AssetManager assetManager = getAssets();
InputStream ims = assetManager.open(
"dict.json"
);
int
size = ims.available();
byte
[] buffer =
new
byte
[size];
ims.read(buffer);
ims.close();
// 41175344
System.out.println(buffer.length);
// java.lang.OutOfMemoryError
String s =
new
String(buffer);
- 執行後就會發生 Out Of Memory1234567891011121314151617181920
7975
AndroidRuntime E FATAL EXCEPTION: main
7975
AndroidRuntime E java.lang.OutOfMemoryError
7975
AndroidRuntime E at java.lang.String.<init>(String.java:
255
)
7975
AndroidRuntime E at java.lang.String.<init>(String.java:
171
)
7975
AndroidRuntime E at java.lang.String.<init>(String.java:
141
)
7975
AndroidRuntime E at org.im.sundictionary.MainActivity.onCreate(MainActivity.java:
66
)
7975
AndroidRuntime E at android.app.Activity.performCreate(Activity.java:
5133
)
7975
AndroidRuntime E at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:
1087
)
7975
AndroidRuntime E at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:
2175
)
7975
AndroidRuntime E at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:
2261
)
7975
AndroidRuntime E at android.app.ActivityThread.access$
600
(ActivityThread.java:
141
)
7975
AndroidRuntime E at android.app.ActivityThread$H.handleMessage(ActivityThread.java:
1256
)
7975
AndroidRuntime E at android.os.Handler.dispatchMessage(Handler.java:
99
)
7975
AndroidRuntime E at android.os.Looper.loop(Looper.java:
137
)
7975
AndroidRuntime E at android.app.ActivityThread.main(ActivityThread.java:
5103
)
7975
AndroidRuntime E at java.lang.reflect.Method.invokeNative(Native Method)
7975
AndroidRuntime E at java.lang.reflect.Method.invoke(Method.java:
525
)
7975
AndroidRuntime E at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:
737
)
7975
AndroidRuntime E at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:
553
)
7975
AndroidRuntime E at dalvik.system.NativeStart.main(Native Method)
分析現場
現場還原了, 但是還是不知道兇手是怎麼樣殺死我的 App 的阿!! 原來是每個手機中各自的 App 可以使用的記憶體上限不同, 也就是有些手機可能是 96M, 而有一些則是 20M.
我們可以透過下面這段程式來瞭解自己手機每個 App 記憶體使用量上限是多少:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int
mMemoryClass = am.getMemoryClass();
long
mLargeMemoryClass = am.getLargeMemoryClass();
而 android:largeHeap="true"
就是告訴系統這個 App 使用量可能會比較大, 請放寬限制!!
什麼!2.3.3 不支援 android:largeHeap="true" ?
雖然現在都是 Android 4.x 居多的時代, 但抱持著研究的精神當然還是得解決 2.3.3 的問題, 現在讓我們來一步一步解決問題吧.
- 建立 2.3 專用的 values 資料夾
- 在
values-v14
下建立bool.xml
- 在
bool.xml
加入<bool name="largeheap">true</bool>
bool.xml
檔案內容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="largeheap">true</bool>
</resources> - 在
AndroidManifst.xml
加入android:largeHeap="@bool/largeheap"
- 大功告成啦!!
參考文獻
- http://stackoverflow.com/questions/14564146/out-of-memory-string-android
- http://stackoverflow.com/questions/14918028/enable-androidlargeheap-in-android-4-and-disable-it-in-android-2-3?answertab=active#tab-top
- http://developer.android.com/guide/topics/manifest/application-element.html
- http://developer.android.com/reference/android/app/ActivityManager.html#getLargeMemoryClass()
- http://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass()
補充
那 largeHeap 的上限到底怎麼設定進去的呢? 那就得看一下 system 的設定檔, 如果你的裝置是 root 就可以使用下面的指令:
adb pull /system/build.prop [指定路徑]
接著打開 build.prop 然後跳到 85 行, 就可以看見你這個裝置的 hepap 的相關設定啦!
如果有興趣也可以看看 system 在 build 的時候的設定檔唷~
https://github.com/android/platformframeworksbase/blob/master/core/jni/AndroidRuntime.cpp#L655
有趣的小發現
在研究的過程竟然發現有人做了一個可以編輯 build.prop 的 App, 作者我就沒有玩過了, 請勇者們去嘗試吧!!
https://play.google.com/store/apps/details?id=org.nathan.jf.build.prop.editor&hl=zh_HK
- Android 踏雷日記(1)String Out Of Memory
- Android 踏雷日記(2)更優雅地解決 String Out Of Memory
- android out of memory
- android Out of memory
- Android Out Of Memory
- android out of memory
- Android Out of Memory (OOM)
- android out of memory初探
- android out of memory(OOM)
- android bitmap out of memory
- Android out of memory(一)
- Android out of memory(二)
- Android Studio out of memory
- android out of memory(OOM)
- matlab:out of memory 1
- android内存溢出问题(out of memory)
- 【转】Android Out Of Memory(OOM)的详细研究
- Android内存溢出(Out Of Memory)…
- 《软件工程》笔记
- 《Thinking in Java》笔记
- linux编程学习5-编写静态库
- 使用git进行版本控制
- python学习笔记
- Android 踏雷日記(1)String Out Of Memory
- 6.14
- 《Android面试宝典》学习笔记(第一章:android入门)
- 《Android面试宝典》学习笔记(第二章:布局)
- 《Android面试宝典》学习笔记(第三章:组件)
- 《Android面试宝典》学习笔记(第四章:对话框、信息提示和菜单)
- 《Android面试宝典》学习笔记(第五章:文件存储)
- 《Android面试宝典》学习笔记(第六章:数据库)
- Activity启动方式四种