B4J Question Memory Leak in Resumable Subs?

Blueforcer

Well-Known Member
Licensed User
Longtime User
I have discovered an endlessly increasing memory usage in my app.
After tracking with VisualVM I noticed that only the resumable subs occupy more and more memory with time. (The shown Allocated Bytes is the delta in 3 Hours!)


The biggest memory consumption comes from this Timer Sub wich increase the Memory around 70 bytes per tick. The Timer ticks the sub every 5 Seconds, but the code will only compute after some time (around every 10 minutes):

B4X:
Sub updateplugins_tick
    For Each App As String In forceUpdates.Keys
        If forceUpdateTime.Get(App) + (forceUpdates.Get(App)*1000) < DateTime.Now Then
            Log("force update "&App)
            forceUpdateTime.Put(App,DateTime.Now)
            Dim Result As Map =plugin.RunPlugin(App, "start", CreateMap("AppDuration":appDuration))
            If Result.Get("needDownload")>0 Then
                For i=1 To Result.Get("needDownload")
                    Dim params As Map
                    params.Initialize
                    params.Put("Handler", Me)
                    params.Put("jobNr", i)
                    wait for (plugin.RunPlugin(App, "download", params)) JobDone(j As HttpJob)
                    params.Put("response", j)
                    plugin.RunPlugin(App, "httpResponse", params)
                    j.Release
                Next
            End If
        End If
        Sleep(100)
    Next
    If (lastUpdateAll + (DB.get("updateInterval")*1000)) < DateTime.Now Then
        lastUpdateAll=DateTime.Now
        If Not(isupdating) Then updateAll
    End If
End Sub

But as you can see, this is not the only resumable Sub wich eats memory.
Also this simple sub:

B4X:
Sub switch
    Dim i As Int = Rnd(1,5)
    Select i
        Case 1
            For y=0 To 8
                drawLine(0,y,31,y,wheel(y*32))
                drawLine(0,y-1,31,y-1,Array As Int(0,0,0))
                show
                Sleep(40)
            Next
        Case 2
            For y=8 To -1 Step -1
                drawLine(0,y,31,y,wheel(y*32))
                drawLine(0,y+1,31,y+1,Array As Int(0,0,0))
                show
                Sleep(40)
            Next
        Case 3
            For x=0 To 32
                drawLine(x,0,x,7,wheel(x*7))
                drawLine(x-1,0,x-1,7,Array As Int(0,0,0))
                show
                Sleep(20)
            Next
        Case 4
            For x=32 To -1 Step-1
                drawLine(x,0,x,7,wheel(x*7))
                drawLine(x+1,0,x+1,7,Array As Int(0,0,0))
                show
                Sleep(20)
            Next
    End Select
    CallSubDelayed(Main,"switchFinish")
End Sub


Is there anything special about Resumable Subs wich i need to know to prevent a Memory Leak?
 
Last edited:

Blueforcer

Well-Known Member
Licensed User
Longtime User
Yes, the posted screenshot shows a memory increase of 150kb in around 2-3 hours from only one sub. of course this is only a short timespan and 150kb wouldnt be that much..but unfortunately it wont stop and increase with every tick. I test it many times

This is from this night for the whole application. The peak comes from the one called jServer website i think, then Javas garbageCollector clean up a bit.


I will switch to ABMonitor to take a deeper look, and maybe i can give a better
diagnosis
 
Last edited:
Upvote 0

Blueforcer

Well-Known Member
Licensed User
Longtime User
Im still fighting against my Memory Leak.
I was able to narrow the problem down by now. it doesn't come dictated by the resumable subs, that was probably only a consequence
Maybe you can help me out anyway.

It comes from following sub (if i uncomment the code inside, the memory usage is stable)

B4X:
Sub updateAll
    lastUpdateAll=DateTime.Now
    isupdating=True
    Log("Update all Apps")
    Log("-----------------------------")
    For Each App In activeApps
        Log("updating "& App)

        Dim downloadCount As Int  =plugin.RunPlugin(App, "downloadCount", Null)
        If downloadCount>0 Then
            For i=1 To downloadCount
                Dim params As Map
                params.Initialize
                params.Put("jobNr", i)
                Dim URL As String = plugin.RunPlugin(App, "startDownload", params)
                Dim j As HttpJob
                j.Initialize("getapps", Me)
                j.Download(URL)
                Wait For JobDone (j As HttpJob)
                params.Put("success",j.Success)
                If j.Success Then
                    params.Put("response",j.GetString)
                    params.Put("InputStream",j.GetInputStream)
                Else
                    Log("Error while downloading data for "&App)
                    Log(j.ErrorMessage)
                End If
                plugin.RunPlugin(App, "httpResponse", params)
                j.Release
            Next
        End If
    Next
    Log("-----------------------------")
    Log("   ")
    isupdating=False
    CallSubDelayed(Me,"data_updated")
End Sub

This code gets the number of Download wich is needed from the Plugin (ABPLugin).
Then it gets every single Download URL, download it and send the Downloaded String or Inputstream back to the Plugin for further processing.
Thats it. The Plugin itselfs just do some Json or textreader things:

B4X:
Sub evalJobResponse(nr As Int,success As Boolean,response As String,InputStream As InputStream) As Boolean
    If success=False Then Return False
    Select nr
        Case 1
            Try
                Dim Reader As TextReader
                Reader.Initialize(InputStream)
                Dim line As String
                line = Reader.ReadLine
                Do While line <> Null
                    If line.Contains("Followers") Then
                        Followers=line.SubString2(line.IndexOf("""")+1,line.IndexOf("Followers")-1)
                        Exit
                    End If
                    line = Reader.ReadLine
                Loop
                Reader.Close
                InputStream.Close
                Return True
            Catch
                Log("Error in: "&PluginName & CRLF & LastException)
                Log("API response: "& CRLF & Reader.ReadAll)
                Return False
            End Try
    End Select
    Return False
End Sub

this code increases my memory consumption every time I call it, and it never stops until i get an OutOfMemory Error.

 
Last edited:
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
I am seeing internal keywords declared as variables. like InputStream as InputStream. Is that even legal?
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Yes but it was relevant to the OP, as that could be the source of the leak. Confusing the GC.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…