Android Question Need Help With Out Of Memory Issues [SOLVED]

Ronomega73

Member
Licensed User
Longtime User
Hi! I've been experiencing out of memory (OOM) problems lately and I could not figure out why. The following figures are returned by the Reflection Library immediately before the line which throws an error:
Max Mem 536,870,912 (0x20000000)
Free Mem 11,523,296 (0xAFD4E0)
Total Mem 16,002,840 (0xF42F18)

I'm still searching this community and other sources for possible solution to the problem. I've already checked for possible leaks (closed up one or two) but the error persists. For now, my questions are:
1. Can the maximum memory be increased in B4A? (LARGEHEAP is already set in the manifest.)
2. Does total memory refer to the amount of memory my app uses?
3. If so, why is my free memory only 11MB when the maximum memory is 536MB (or 512MB)?

By the way, the OOM error shows at the line which reads a 300-byte file using randomaccessfile's readb4xobject.
Thanks a lot for any help you could share on this. God bless!
 

Ronomega73

Member
Licensed User
Longtime User
Here's the error message and the stack trace log (it's my first time to use stack trace. I hope I'm doing it correctly.)

****************
com.oms.readingmachine.login: _loadusertasklogs
com.oms.readingmachine.login$ResumableSub_btnLogin_Click: resume
com.oms.readingmachine.login: _btnlogin_click
java.lang.reflect.Method: invoke
anywheresoftware.b4a.BA: raiseEvent2
anywheresoftware.b4a.BA: raiseEvent2
anywheresoftware.b4a.BA: raiseEvent
anywheresoftware.b4a.objects.ViewWrapper$1: onClick
android.view.View: performClick
android.widget.TextView: performClick
android.view.View: performClickInternal
android.view.View: access$3200
android.view.View$PerformClick: run
android.os.Handler: handleCallback
android.os.Handler: dispatchMessage
android.os.Looper: loop
android.app.ActivityThread: main
java.lang.reflect.Method: invoke
com.android.internal.os.RuntimeInit$MethodAndArgsCaller: run
com.android.internal.os.ZygoteInit: main
login_loadusertasklogs (java line: 1995)
java.lang.OutOfMemoryError: Failed to allocate a 825306944 byte allocation with 12582912 free bytes and 509MB until OOM, max allowed footprint 15044312, growth limit 536870912
at anywheresoftware.b4a.randomaccessfile.RandomAccessFile.ReadB4XObject(RandomAccessFile.java:338)
at com.oms.readingmachine.login._loadusertasklogs(login.java:1995)
at com.oms.readingmachine.login$ResumableSub_btnLogin_Click.resume(login.java:1112)
at com.oms.readingmachine.login._btnlogin_click(login.java:972)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:205)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
at android.view.View.performClick(View.java:7354)
at android.widget.TextView.performClick(TextView.java:14263)
at android.view.View.performClickInternal(View.java:7320)
at android.view.View.access$3200(View.java:846)
at android.view.View$PerformClick.run(View.java:27880)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7258)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
 
Upvote 0

Ronomega73

Member
Licensed User
Longtime User
Hello again. Here's just an update on this issue. Last night I tried to create a new file using WriteB4XObject. When I read it with ReadB4XObject, it still threw an Out Of Memory error. I also did what Erel suggested above but, strangely, the same error occurred. This morning, I did a factory reset of the device I am using (Samsung A20s) because it's WiFi no longer functions (saw some cracks on its tempered glass so someone must have experimented with gravity using it). When I tried to run the app again, the error went away. I'm not sure if this is for good or it's just so because the app is not yet loaded with many user data. I will just post here later if there's more to update.
 
Upvote 0

Ronomega73

Member
Licensed User
Longtime User
Another late update (I was very busy with test papers this week). Just in case someone who has the same memory problem, the factory reset I did as mentioned above didn't work for long. I'm back to getting the out of memory problem. Here are the other things I did so far in an attempt to solve the problem, creating a new file on each compile/run:
-- used B4XSerializator instead, as suggested by Erel above
-- initialized the List contained inside the user type I'm trying to save to and read from the file
-- removed the list altogether
-- tried to read only a single data entry from file (to remove the Do-Loop)
-- set all the variables to simple data (123 for Int, "text" for string, etc.) to ensure correct ones are being saved to file
-- (BUT THIS ONE WORKS FINE!!!) tried to save/read bitmaps instead (many times bigger in size) on the very line that generate the OOM error
Therefore, I think the problem is in the user type I'm trying to save to/read from the file. It is declared in the Main module this way:
B4X:
     Type UserLog(DateTime_Start As Long, TaskDuration As Int, ReadingMaterialTitle As String, ReadingMaterialFname As String, TotalWords As Int, SkippedWords As String, PercentDone As Int, Score As Int, SpeedWPM As Int, Remarks As String)

And, it is saved this way:

B4X:
    Dim newlog As UserLog
    newlog.Initialize
    newlog.DateTime_Start = 123456789 'Main.CurUserLog.DateTime_Start
    newlog.PercentDone = 123 'Main.CurUserLog.PercentDone
    newlog.ReadingMaterialFname = "try string"  'Main.CurUserLog.ReadingMaterialFname
    newlog.ReadingMaterialTitle = "Sample Title" 'Main.CurUserLog.ReadingMaterialTitle.Replace(",", "")
    newlog.Remarks = "Remarks" 'Main.CurUserLog.Remarks
    newlog.Score = 123 'Main.CurUserLog.Score
    newlog.SkippedWords = "tryskip" 'Main.CurUserLog.SkippedWords
    newlog.SpeedWPM = 123 'Main.CurUserLog.SpeedWPM
    newlog.TaskDuration = 123 'Main.CurUserLog.TaskDuration
    newlog.TotalWords = 123 'Main.CurUserLog.TotalWords
    Main.lstSessionLogs.Add(newlog) 'add to current session's logs
    'append new data to file right away
    Dim ufile As String
    If Login.CurUserInfo.IsInitialized Then
        If Login.CurUserInfo.Username.Trim <> "" Then
            ufile = Login.CurUserInfo.Username.Trim & "_tlogs.dat"
        Else
            ufile = "UserTaskLogs2.dat"
        End If
    Else
        ufile = "UserTaskLogs2.dat"
    End If
    Log("ufile:" & ufile)
    Dim raf As RandomAccessFile
    raf.Initialize(File.DirInternal, ufile, False)
    raf.WriteB4XObject(newlog, raf.Size) 'add to end of file
    raf.Close

It is read from file using this code:

B4X:
    If File.Exists(File.DirInternal, ufile) = True Then
        Dim raf As RandomAccessFile
        raf.Initialize(File.DirInternal, ufile, True)
        Do While raf.CurrentPosition < raf.Size
            Dim UL As UserLog
            UL = raf.ReadB4XObject(raf.CurrentPosition) '<------this line throws the OOM error
            Main.lstUserTaskLogs.Add(UL)
        Loop
        raf.Close
    End If
 
Last edited:
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
And, it is saved this way
you are STILL using randonaccessfile instead of B4XSerializator which Erel suggested to use. Why?

If you have a list of costumtypes. Why are you writing only one type to a file. Why are you not writing the full LIST at once and read the list at once?

B4X:
Dim ser As B4XSerializator
File.WriteBytes(XUI.DirDefault, "file.dat", ser.ConvertObjectToBytes(Main.lstUserTaskLogs))

' Read back the full list from file.
Dim obj2 As List = ser.ConvertBytesToObject(File.ReadBytes(XUI.DirDefault, "file.dat"))
 
Upvote 0

Ronomega73

Member
Licensed User
Longtime User
Thanks @DonManfred for the reply. I did not use B4XSerializator (at least not in this file IO task) because, aside from that I still got the out of memory error, I find it easier using RandomAccessFile to add more objects to file without monitoring objects' byte sizes. Saving the entire list at once to file (such saving is often done in this project) might slow down my app when the list grows big (it is bound to become huge because it will contain users' task logs). Also, I fear (which may be unfounded) that continuous saving and deleting a huge file to storage might shorten its lifespan. With RAF, I could keep adding more data to file and reading them without ever deleting the same file.

I've been using RAF since I learned about it and it has always worked fine. Even in my other project, which is way bigger (around 40K+ lines of code) than this current project , RAF is intensively used saving and loading multimedia files with not a single out of memory problem. BTW, in this current app, I'm using a speech recognition lib which uses a 64mb voice model, but I don't think it is the problem because my previously compiled app still runs well in all of my students' devices. Besides, as I mentioned above, the app works fine if I load a couple of bitmaps (8MB) instead of the user type (60bytes). I just could not figure out (yet) what changes caused this error. It all started when I added multi-user feature to this app.

Thanks @walt61 for the attached project. I tried running it here and it works fine also. I'll do my best to upload a smaller project that reproduces the error.

I'll try to drop the user type in question altogether and create a brand new one. I will post updates next week.
 
Upvote 0

Ronomega73

Member
Licensed User
Longtime User
Sorry for this late update to this issue. It's already solved (kind of). What I did was I dropped the user type and replaced it with a map type. I've been running the app ever since without memory problems. Thanks, everyone.
 
Upvote 0
Top