Italian Memoria esaurita nel caricare una bitmap

AlpVir

Well-Known Member
Licensed User
Longtime User
Non ne riesco a venire a capo !!!
La sub seguente :
B4X:
Sub PreparaElementiContenitori 
   CurrentPointerId=-1
   CurrentX=0
   CurrentY=0
   MinDragMove= 10
   Panel1.Initialize("") 
   Activity.AddView(Panel1, 0, 0, Main.LargSchermo , Main.AltSchermo )
   Canvas1.Initialize(Panel1)
   If BMP.IsInitialized Then
      Dim Obj1 As Reflector
      Obj1.Target = BMP 
      Obj1.RunMethod("recycle")
   End If   

   Log ("qui parte l'errore")
   BMP.Initialize(File.DirRootExternal , Main.NomeFile)
   ' BMP.InitializeSample (File.DirRootExternal , Main.NomeFile, intLargImmagine, 600 ) 
   Log ("se c'è errore questo messaggio non appare mai")

   DestRect.Initialize(CurrentX, CurrentY, BMP.Width-CurrentX, BMP.Height-CurrentY)
   SrcRect.Initialize(0, 0, BMP.Width, BMP.Height)
   Gestures1.SetOnTouchListener(Panel1, "Handle_Touch")
   DisegnaBitmap(0, 0)
End Sub

viene richiamata per caricare una immagine JPG di 946 KB. Tutto OK !
Poi, tramite opportuni comandi, l'utilizzatore carica una diversa immagine (diciamo di 400 KB). Ancora tutto OK !
Successivamente l'utilizzatore carica la precedente immagine di 946 KB. Ed appare l'errore, apparentemente in :
B4X:
BMP.Initialize(File.DirRootExternal , Main.NomeFile)

Questo è il log relativo :
qui parte l'errore
panorama_preparaelementicontenitori (B4A line: 113)
BMP.Initialize(File.DirRootExternal , Main.NomeFile)
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:525)
at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize2(CanvasWrapper.java:498)
at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize(CanvasWrapper.java:491)
at alpvir.panorami.panorama._preparaelementicontenitori(panorama.java:2644)
at alpvir.panorami.panorama._activity_create(panorama.java:390)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
at alpvir.panorami.panorama.afterFirstLayout(panorama.java:84)
at alpvir.panorami.panorama.access$100(panorama.java:16)
at alpvir.panorami.panorama$WaitForLayout.run(panorama.java:72)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3806)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)

Ma, mi domando io, con le istruzioni
B4X:
If BMP.IsInitialized Then
      Dim Obj1 As Reflector
      Obj1.Target = BMP 
      Obj1.RunMethod("recycle")
   End If
non si azzera la memoria impegnata dalla bitmap ? E quindi la memoria è libera per caricare qualche bitmap, giusto ?
Dove sbaglio ?
Grazie per l'attenzione !
 
Last edited:

arenaluigi

Well-Known Member
Licensed User
Longtime User
Scusa ma non vedo dove fai l'azzeramento degli oggetti dell'activity.

Inoltre hai verificato la memoria assegnata all'emulatore ?se non sbagli di default è 24.
Per farlo apri avd manager, poi fai l'edit e c'è un campo in basso chiamato:
"Max VM Application Heap Size" prova a portarlo a 48.
Facci sapere
CIao
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Scusa ma non vedo dove fai l'azzeramento degli oggetti dell'activity.
L'activity "Main" ha una serie di radio button ciascuno dei quali avvia l'archivity "Panorama" e carica una diversa immagine JPG. Col tasto back si esce da "Panorama" e si ritorna a "Main".
Questo è il meccanismo. Caricando, uno dopo l'altro, immagini di 500-600-700 KB tutto è OK.
Inoltre hai verificato la memoria assegnata all'emulatore ?se non sbagli di default è 24.
Sperimento direttamente nel device (Motorola Defy Plus).

L'app in questione è liberamente scaricabile al link Software, pienamente funzionante (tranne il difetto qui segnalato).
Grazie e ciao.
 

genesi

Active Member
Licensed User
Longtime User
Ma said:
mi domando io[/B], con le istruzioni
B4X:
If BMP.IsInitialized Then
      Dim Obj1 As Reflector
      Obj1.Target = BMP 
      Obj1.RunMethod("recycle")
   End If
non si azzera la memoria impegnata dalla bitmap ? E quindi la memoria è libera per caricare qualche bitmap, giusto ?
Dove sbaglio ?
Grazie per l'attenzione !
Ciao , mi sembra che in effetti la memoria non sia rilasciata ma solo marcata come "dead" per il Garbage collected , quindi parova a richiamarlo dopo il recycle. Un altro problema potrebbe venire dal cambio di orientamento del device.
Mario
 

AlpVir

Well-Known Member
Licensed User
Longtime User
@genesi
quindi parova a richiamarlo dopo il recycle
Come ?

Riguardo l'orientamento non ci sono problemi. L'app è bloccata in modalità "landscape".
Grazie e ciao.
 

genesi

Active Member
Licensed User
Longtime User
@genesi

Come ?
B4X:
Dim r As Reflector
r.RunStaticMethod("java.lang.System", "gc", Null, Null)
anche se prima di dare out of memory il sistema dovrebbe fare un GC
prova anche ad impostare a NUL l'immagine
BMP=Null
Mario
 

AlpVir

Well-Known Member
Licensed User
Longtime User
@genesi

Già fatto, senza alcun risultato.
Ho inserito ... RunStaticMethod ... sia prima che dopo ... recycle ...
Ho anche provato un

For i=1 To 4
Obj1.RunStaticMethod("java.lang.System", "gc", Null, Null)
Next

Anche BMP = Null pare non avere effetto.

Nulla !
 

genesi

Active Member
Licensed User
Longtime User
:sign0080: bella fregatura.
Sembra che non ci sia certezza su quando il GC agisca e quindi la coda delle immagini esaurisce l'heap
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Bella fregatura sì !
Tuttavia sembrerebbe che sia Android a prendersi il carico di fare la garbage collection, anche se è possibile (con il codice che mi hai segnalato) forzarla.
Mi viene anche segnalato che con altri device l'errore di memoria esaurita avviene con particolari immagini (alias panorami; ad esempio l'Aiera che effettivamente è assai "pesante"). Oppure dopo aver caricato, in successione, 4 o 5 panorami più "leggeri". Sembra che ogni device si comporti in modo lievemente differente ed evidenzi l'errore in diverso modo, probabilmente in funzione della memoria libera che esso possiede.
Hai provato a scaricarti la mia app rendendoti conto di quanto dico e magari fornendomi nuovi particolari ?
Il panorama di 946 KB citato nel primo post è "CUNEO". Uno "leggero" è "CUCUJA".
Riprendo la prima riga del mio primo post
Non ne riesco a venire a capo !!!
Grazie e ciao
 

genesi

Active Member
Licensed User
Longtime User
Bella fregatura sì !
Tuttavia sembrerebbe che sia Android a prendersi il carico di fare la garbage collection
Si il/la GC è a carico del sistema operativo e quindi con versioni di Android differenti l'errore potrebbe non verificarsi, questo anche con device diversi.
Da quello che ho capito è che il recycle+Nul+gc ( quest'ultimo opzionale) in alcuni casi ha risolto il problema.
Importante controlla che se hai un canvas con riferimento alla bitmap DEVI cancellare questo riferimento
mario
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Importante controlla che se hai un canvas con riferimento alla bitmap DEVI cancellare questo riferimento
Già fatto ! Nulla !
 
Top