Android:读取txt文件很慢并且将数据插入trie时内存泄漏(错误的hashmap使用)?
我正在尝试在我的 android 应用程序中读取 816 KB txt 文件(70 000 行),该文件包含在 res/raw 文件夹中。这是相关的代码片段:
InputStream raw = context.getResources().openRawResource(R.raw.alpha);
InputStreamReader inputreader = new InputStreamReader(raw);
BufferedReader r = new BufferedReader(inputreader);
String line;
int j = 0;
while ((line = r.readLine()) != null && j < 90000){
theTrie.insert(line);
j++;
}
“上下文”是通过参数给出的:Main.readDatabase(getApplication());
这个版本崩溃并显示以下日志:
10-04 21:14:26.096: INFO/dalvikvm(1327): | group="main" sCount=0 dsCount=0 obj=0x4001f1a8 self=0xce48
10-04 21:14:26.096: INFO/dalvikvm(1327): | sysTid=1327 nice=0 sched=0/0 cgrp=default handle=-1345006528
10-04 21:14:26.096: INFO/dalvikvm(1327): | schedstat=( 3112456663 436561269 431 )
10-04 21:14:26.096: INFO/dalvikvm(1327): at java.lang.Throwable.nativeFillInStackTrace(Native Method)
10-04 21:14:26.096: INFO/dalvikvm(1327): at java.lang.Throwable.fillInStackTrace(Throwable.java:135)
10-04 21:14:26.096: INFO/dalvikvm(1327): at java.lang.Throwable.<init>(Throwable.java:74)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.Error.<init>(Error.java:38)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.VirtualMachineError.<init>(VirtualMachineError.java:36)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.OutOfMemoryError.<init>(OutOfMemoryError.java:34)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.util.HashMap.makeTable(HashMap.java:-1)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.util.HashMap.<init>(HashMap.java:162)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.TrieNode.<init>(TrieNode.java:21)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.Trie.insert(Trie.java:27)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.Main.readDatabase(Main.java:356)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.SoftKeyboard.onCreate(SoftKeyboard.java:89)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread.handleCreateService(ActivityThread.java:1920)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread.access$2500(ActivityThread.java:117)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:982)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.os.Handler.dispatchMessage(Handler.java:99)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.os.Looper.loop(Looper.java:123)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread.main(ActivityThread.java:3647)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.reflect.Method.invokeNative(Native Method)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.reflect.Method.invoke(Method.java:507)
10-04 21:14:26.106: INFO/dalvikvm(1327): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-04 21:14:26.106: INFO/dalvikvm(1327): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-04 21:14:26.106: INFO/dalvikvm(1327): at dalvik.system.NativeStart.main(Native Method)
10-04 21:14:26.196: WARN/dalvikvm(1327): Exception thrown (Ljava/lang/OutOfMemoryError;) while throwing internal exception (Ljava/lang/OutOfMemoryError;)
10-04 21:14:26.326: INFO/dalvikvm-heap(1327): Clamp target GC heap from 25.881MB to 24.000MB
10-04 21:14:26.326: DEBUG/dalvikvm(1327): GC_CONCURRENT freed <1K, 13% free 20224K/22983K, external 1625K/2137K, paused 2ms+3ms
10-04 21:14:26.446: INFO/dalvikvm-heap(1327): Clamp target GC heap from 25.856MB to 24.000MB
10-04 21:14:26.446: DEBUG/dalvikvm(1327): GC_FOR_MALLOC freed 25K, 13% free 20198K/22983K, external 1625K/2137K, paused 123ms
10-04 21:14:26.446: DEBUG/AndroidRuntime(1327): Shutting down VM
如果我不在模拟器中运行此代码(由于文件读取而略有改变),但在普通的 java 应用程序中它运行良好,没有任何问题,但在 Android 上似乎存在内存泄漏?有人知道可能是什么问题吗? 即使我删除了“theTrie.insert(line);”行因此,while 循环(几乎)为空,应用程序需要 2.1 秒来“读取”800 kb。这不可能是正常的吧?我的错误在哪里?
提前致谢!
更新: 我用 DDMS 转储了一个堆文件并用 MAT 对其进行了分析。它说:由“dalvik.system.PathClassLoader @ 0x4051d5e8”加载的类[有问题]占用 23.951.808 (91,76%) 字节。内存累积在“”加载的“java.util.HashMap$HashMapEntry[]”的一个实例中。 直方图列出了 java.util.HashMap$HashMapEntry[]、java.util.HashMap 和 java.util.HashMap$HashMapEntry 作为浅堆最大的三个对象。
这是我关于 hashmap 使用的代码(在定义 trie 节点的类中):
public Map<Character, TrieNode> children;
public TrieNode(char letter) {
this.letter = letter;
children = new HashMap<Character, TrieNode>(26);
}
是什么导致了内存泄漏?
I'm trying to read a 816 KB txt file (70 000 lines) in my android app which is contained in the res/raw folder. This is the relevant code snippet:
InputStream raw = context.getResources().openRawResource(R.raw.alpha);
InputStreamReader inputreader = new InputStreamReader(raw);
BufferedReader r = new BufferedReader(inputreader);
String line;
int j = 0;
while ((line = r.readLine()) != null && j < 90000){
theTrie.insert(line);
j++;
}
The "context" is given via a parameter: Main.readDatabase(getApplication());
This version crashes with the following log:
10-04 21:14:26.096: INFO/dalvikvm(1327): | group="main" sCount=0 dsCount=0 obj=0x4001f1a8 self=0xce48
10-04 21:14:26.096: INFO/dalvikvm(1327): | sysTid=1327 nice=0 sched=0/0 cgrp=default handle=-1345006528
10-04 21:14:26.096: INFO/dalvikvm(1327): | schedstat=( 3112456663 436561269 431 )
10-04 21:14:26.096: INFO/dalvikvm(1327): at java.lang.Throwable.nativeFillInStackTrace(Native Method)
10-04 21:14:26.096: INFO/dalvikvm(1327): at java.lang.Throwable.fillInStackTrace(Throwable.java:135)
10-04 21:14:26.096: INFO/dalvikvm(1327): at java.lang.Throwable.<init>(Throwable.java:74)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.Error.<init>(Error.java:38)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.VirtualMachineError.<init>(VirtualMachineError.java:36)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.OutOfMemoryError.<init>(OutOfMemoryError.java:34)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.util.HashMap.makeTable(HashMap.java:-1)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.util.HashMap.<init>(HashMap.java:162)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.TrieNode.<init>(TrieNode.java:21)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.Trie.insert(Trie.java:27)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.Main.readDatabase(Main.java:356)
10-04 21:14:26.106: INFO/dalvikvm(1327): at snappy.keyboard.SoftKeyboard.onCreate(SoftKeyboard.java:89)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread.handleCreateService(ActivityThread.java:1920)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread.access$2500(ActivityThread.java:117)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:982)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.os.Handler.dispatchMessage(Handler.java:99)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.os.Looper.loop(Looper.java:123)
10-04 21:14:26.106: INFO/dalvikvm(1327): at android.app.ActivityThread.main(ActivityThread.java:3647)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.reflect.Method.invokeNative(Native Method)
10-04 21:14:26.106: INFO/dalvikvm(1327): at java.lang.reflect.Method.invoke(Method.java:507)
10-04 21:14:26.106: INFO/dalvikvm(1327): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-04 21:14:26.106: INFO/dalvikvm(1327): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-04 21:14:26.106: INFO/dalvikvm(1327): at dalvik.system.NativeStart.main(Native Method)
10-04 21:14:26.196: WARN/dalvikvm(1327): Exception thrown (Ljava/lang/OutOfMemoryError;) while throwing internal exception (Ljava/lang/OutOfMemoryError;)
10-04 21:14:26.326: INFO/dalvikvm-heap(1327): Clamp target GC heap from 25.881MB to 24.000MB
10-04 21:14:26.326: DEBUG/dalvikvm(1327): GC_CONCURRENT freed <1K, 13% free 20224K/22983K, external 1625K/2137K, paused 2ms+3ms
10-04 21:14:26.446: INFO/dalvikvm-heap(1327): Clamp target GC heap from 25.856MB to 24.000MB
10-04 21:14:26.446: DEBUG/dalvikvm(1327): GC_FOR_MALLOC freed 25K, 13% free 20198K/22983K, external 1625K/2137K, paused 123ms
10-04 21:14:26.446: DEBUG/AndroidRuntime(1327): Shutting down VM
If I don't run this code (slightly changed due to file reading) in the emulator but in a normal java application it runs fine without any problems but on Android there seems to be a memory leak? Does somebody have any idea what could be the problem?
Even if I delete the line "theTrie.insert(line);" so that the while loop is (nearly) empty the app needs 2,1 seconds for "readlining" the 800 kb. This can't be normal, right? Where is my mistake?
Thanks in advance!
Update:
I dumped a heap file with DDMS and analyzed it with MAT. It says: The class [in question], loaded by "dalvik.system.PathClassLoader @ 0x4051d5e8", occupies 23.951.808 (91,76%) bytes. The memory is accumulated in one instance of "java.util.HashMap$HashMapEntry[]" loaded by "".
The histogram lists java.util.HashMap$HashMapEntry[], java.util.HashMap and java.util.HashMap$HashMapEntry as the three objects with the largest shallow heap.
Here is my code regarding the hashmap use (in the class thats defining the node of the trie):
public Map<Character, TrieNode> children;
public TrieNode(char letter) {
this.letter = letter;
children = new HashMap<Character, TrieNode>(26);
}
Whats causing the memory leak?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有时模拟器并不像我们中的一些人想要的那么准确。有时,某些在终端中运行良好的进程在模拟器中运行缓慢。
使用 Android 手机尝试一下,然后别忘了告诉我们您的体验。
-------------------------------------------------------- 修改
这个:
然后看看你调用这个函数多少次,也许这就是问题所在。
但是,思考并查看 trie 地图,我也可以告诉您对您正在阅读的内容进行投资,也许行太长了。
-------------------------------------------------------- 修改 2< /strong>
我认为你能做的最好的事情就是改变观点并尝试使用 SQLite 数据库来获得如此多的信息并且没有内存问题。
Sometimes the emulator is not so much accurate than some of we would want . Sometimes some process which runs nicely in a terminal , runs slow in emulator .
Try it with an android's phone and then don't forget to tell us with your experience.
-------------------------------------------- MODIFY
Try this:
And then see how many times do you call this function , maybe that's the problem.
But , thinking about and seeing trie map , i can tell you too make an invest about what are you reading ,maybe the lines are too long .
-------------------------------------------- MODIFY 2
I think the best you can do is change the point of view and try to use a SQLite db to have so much info and without problems of memory.