简体   繁体   English

Android 应用程序在 EDF 文件解析时运行到 java.lang.OutOfMemoryError

[英]Android App running into java.lang.OutOfMemoryError while EDF file parsing

I have searched around for simmilar topics but could not find anything related to EDF files and Out of memory error together.我搜索了类似的主题,但找不到任何与 EDF 文件和 Out of memory 错误相关的内容。

So, here is my problem: I am developing an Android app in Android studio which browses files, selects an '.edf' file and parses it.所以,这是我的问题:我正在 Android 工作室开发一个 Android 应用程序,它浏览文件,选择一个“.edf”文件并解析它。 But for some files it throws the following error (with stacktrace):但是对于某些文件,它会引发以下错误(带有堆栈跟踪):

I/xample.styleap: Starting a blocking GC Alloc
    Starting a blocking GC Alloc
I/xample.styleap: Alloc concurrent copying GC freed 15804(1107KB) AllocSpace objects, 5(108KB) LOS objects, 86% free, 1955KB/13MB, paused 148us total 44.577ms
    Starting a blocking GC Alloc
I/xample.styleap: Alloc young concurrent copying GC freed 0(15KB) AllocSpace objects, 0(0B) LOS objects, 86% free, 1955KB/13MB, paused 120us total 16.603ms
    Starting a blocking GC Alloc
I/xample.styleap: Alloc concurrent copying GC freed 2019(110KB) AllocSpace objects, 0(0B) LOS objects, 86% free, 1844KB/13MB, paused 83us total 25.049ms
    Forcing collection of SoftReferences for 488MB allocation
    Starting a blocking GC Alloc
I/xample.styleap: Alloc concurrent copying GC freed 2053(69KB) AllocSpace objects, 0(0B) LOS objects, 87% free, 1790KB/13MB, paused 75us total 22.140ms
W/xample.styleap: Throwing OutOfMemoryError "Failed to allocate a 512000012 byte allocation with 12582912 free bytes and 190MB until OOM, target footprint 14416192, growth limit 201326592" (VmSize 1212600 kB)
I/xample.styleap: Starting a blocking GC Alloc
    Starting a blocking GC Alloc
I/xample.styleap: Alloc young concurrent copying GC freed 4(31KB) AllocSpace objects, 0(0B) LOS objects, 87% free, 1774KB/13MB, paused 79us total 15.057ms
I/xample.styleap: Starting a blocking GC Alloc
I/xample.styleap: Alloc concurrent copying GC freed 3(16KB) AllocSpace objects, 0(0B) LOS objects, 87% free, 1774KB/13MB, paused 83us total 23.495ms
    Forcing collection of SoftReferences for 488MB allocation
    Starting a blocking GC Alloc
I/xample.styleap: Alloc concurrent copying GC freed 50(17KB) AllocSpace objects, 0(0B) LOS objects, 87% free, 1788KB/13MB, paused 73us total 22.532ms
W/xample.styleap: Throwing OutOfMemoryError "Failed to allocate a 512000016 byte allocation with 12582912 free bytes and 190MB until OOM, target footprint 14414784, growth limit 201326592" (VmSize 1212600 kB)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.styleapp, PID: 30041
    java.lang.OutOfMemoryError: Failed to allocate a 512000016 byte allocation with 12582912 free bytes and 190MB until OOM, target footprint 14414784, growth limit 201326592
        at br.unb.biologiaanimal.edf.EDFReader.readRecords(EDFReader.java:106)
        at br.unb.biologiaanimal.edf.EDFReader.<init>(EDFReader.java:25)
        at br.unb.biologiaanimal.edf.EDF.<init>(EDF.java:24)
        at com.example.styleapp.MainActivity.runEDFfile(MainActivity.java:100)
        at com.example.styleapp.MainActivity.access$000(MainActivity.java:24)
        at com.example.styleapp.MainActivity$2.onMenuItemClick(MainActivity.java:82)
        at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:154)
        at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:991)
        at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:981)
        at androidx.appcompat.widget.ActionMenuView.invokeItem(ActionMenuView.java:625)
        at androidx.appcompat.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:151)
        at android.view.View.performClick(View.java:7140)
        at android.view.View.performClickInternal(View.java:7117)
        at android.view.View.access$3500(View.java:801)
        at android.view.View$PerformClick.run(View.java:27355)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7410)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
W/System: A resource failed to call close.

I am using EDF parser library for java: https://github.com/lab-neuro-comp/EDF我正在为 java 使用 EDF 解析器库: https://github.com/lab-neuro-comp/EDF

My source code (MainActivity.java):我的源代码(MainActivity.java):

import br.unb.biologiaanimal.edf.EDF;
EDF edf = new EDF(filepath);

It fails while EDF constructor is called with the specific filepath.当使用特定文件路径调用 EDF 构造函数时,它会失败。 At many places, it has been said that it fails due to shortage of VM in JVM/Android or heap size.很多地方都说它失败的原因是 JVM/Android 中的 VM 不足或堆大小。 But i think i have taken care of that too:但我想我也已经处理好了:

Inside studio.vmoptions里面 studio.vmoptions

-Xmx2048m

I guess this specifies Android Studio's JVM VM size.我猜这指定了 Android Studio 的 JVM VM 大小。 Am also printing maximum amount of memory that the Java virtual machine will attempt to use:我还打印了 Java 虚拟机将尝试使用的 memory 的最大数量:

Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();

This prints这打印

201326592 201326592

That means 201MB approx is available.这意味着大约有 201MB 可用。

Then what is the reason for it fails (runs out of memory) while loading a 1.9 MB EDF file when it successfuly loads a 4.2MB EDF file?那么,当它成功加载 4.2MB EDF 文件时,它在加载 1.9 MB EDF 文件时失败(内存不足)的原因是什么?

It was failing because of a logical bug of the EDF parsing library.由于 EDF 解析库的逻辑错误,它失败了。 The EDF class method looks for a header called "duration" (the reason is unclear) and uses it for subsequent arithmetic operations where it use the header value to allocate array memory etc. at times the duration value is float and that leads to wrong arithmetic also the resultant values become significantly large. The EDF class method looks for a header called "duration" (the reason is unclear) and uses it for subsequent arithmetic operations where it use the header value to allocate array memory etc. at times the duration value is float and that leads to wrong arithmetic结果值也变得非常大。 There it fails to allocate memory.在那里它无法分配 memory。 here is the snippet of the code:这是代码片段:

private void readRecords(FileInputStream stream)
    throws IOException
    {
        records = new HashMap();
        int[] numberSamples = getNumberSamples();
        int[] sampling = new int[numberSignals];
        int duration = paramToInt("duration");
        int dataRecords = paramToInt("datarecords");
        byte[][] recordList = new byte[numberSignals][5];
        String[] labels = getLabels();
        byte[] buffer = null;

        // Initalizing variables
        for (int i = 0; i < numberSignals; ++i)
        {
            sampling[i] = duration * numberSamples[i];
            recordList[i] = null;
        }

        // Reading records
        for (int d = 0; d < dataRecords; ++d)
        {
            for (int i = 0; i < numberSignals; ++i)
            {
                duration = 2 * sampling[i];
                buffer = new byte[duration];
                stream.read(buffer);
                // TODO Make this insertion faster. Maybe a queue?
                recordList[i] = (recordList[i] == null)?
                    buffer :
                    EDFUtil.insert(recordList[i], buffer);
            }
        }

        // Packing records
        for (int i = 0; i < numberSignals; ++i)
        {
            String label = labels[i].trim();
            records.put(label, recordList[i]);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM