Android Приложение работает с ошибкой java .lang.OutOfMemoryError во время синтаксического анализа файла EDF - PullRequest
1 голос
/ 27 мая 2020

Я искал похожие темы, но не смог найти ничего, связанного с файлами EDF и ошибкой Out of memory вместе.

Итак, вот моя проблема: Я разрабатываю Android в студии Android, которая просматривает файлы, выбирает файл .edf и анализирует его. Но для некоторых файлов возникает следующая ошибка (с трассировкой стека):

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.

Я использую библиотеку анализатора EDF для java: https://github.com/lab-neuro-comp/EDF

Мой исходный код (MainActivity. java):

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

Он не работает, пока конструктор EDF вызывается с указанным c путем к файлу. Во многих местах было сказано, что он не работает из-за нехватки виртуальной машины в JVM / Android или размера кучи. Но я думаю, что я тоже позаботился об этом:

Inside studio.vmoptions

-Xmx2048m

Я предполагаю, что это указывает Android размер виртуальной машины JVM Studio. Я также печатаю максимальный объем памяти, который виртуальная машина Java попытается использовать:

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

Это печатает

201326592

Это означает, что доступно около 201 МБ.

Тогда в чем причина сбоя (заканчивается нехватка памяти) при загрузке файла EDF размером 1,9 МБ, когда он успешно загружает файл EDF размером 4,2 МБ?

1 Ответ

1 голос
/ 27 мая 2020

Ошибка из-за логической ошибки библиотеки синтаксического анализа EDF. Метод класса EDF ищет заголовок с именем «duration» (причина неясна) и использует его для последующих арифметических c операций, где он использует значение заголовка для выделения памяти массива et c. время от времени значение продолжительности является плавающим, что приводит к неправильной арифметике c, а также результирующие значения становятся значительно большими. Там не удается выделить память. вот фрагмент кода:

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]);
        }
    }
...