2009-12-22 19 views
29

Bitmap nesneleri ve bellek ve genel sınıflandırmaları ile ilgili birkaç sorum var.Android'de Bitmapler

  1. Bellek içi veya yerel bitmap nedir?
  2. Bitmap belleği Yığın belleğinden nasıl farklıdır? yerine Java new anahtar kelime daha

cevap

33

yerli kod (malloc()) kullanılarak tahsis edilmiş olan bir Bitmap nesnesi destek belleği. Bu, belleğin Dalvik tarafından değil, doğrudan işletim sistemi tarafından yönetildiği anlamına gelir.

Yerel yığın ve Dalvik'in yığını arasındaki tek gerçek fark, Dalvik'in yığınının çöp toplanması ve yerel olanın olmamasıdır.

Bu amaçlar için, burada pek bir fark yok. Bitmap nesnesiniz çöp topladığında, yıkıcı ilgili belleği yerel yığında geri dönüştürür.

Kaynak:

+0

Bu hatanın giderilip giderilmediğini biliyor musunuz? Şu anda gökgürültüsünde aynı problemle karşılaşıyorum. Bitmapleri geri dönüştürüyorum ancak yerel yığında hiçbir zaman oom hatalarına neden olan hiçbir alanı temizlemiyorlar. –

+5

Sadece netlik için, yukarıdaki cevap android sürümü 2.x ve aşağısı için geçerlidir. Android 3 ile başlayarak, bitmap örnekleri, karşı yığını agains. Bu kolayca kontrol edilebilir: android 2.x bir bitmap oluşturarak Java yığın boyutu oldukça fazla dokunmuş, Adnroid 3.x içinde oluştururken Java yığınına çok sayıda bayt katacak. –

+0

Ah! Yani saymanın artık çok daha sezgisel olduğunu söylüyorsun? Bu harika - herkes için yerel yığın ile android yığın toplamak için hacky kodu yazdı tüm hariç ... –

32

burada önemli incelik vardır: Bitmap piksel yerel yığın tahsis olsa, Dalvik yolunda bazı özel hileler Java yığınına karşı muhasebeleştirilmelidir. Bu iki nedenden dolayı yapılır:

(1) Bellek miktarını kontrol etmek için bir uygulama bunu ayırır. Muhasebe olmadan, bir uygulama büyük miktarda bellek ayırabilir (Bitmap nesnesinin kendisi çok küçük olduğu halde, keyfi olarak büyük miktarda yerel bellek tutabilir), 16MB veya 24MB yığın sınırının ötesine uzanabilir.

(2) GC'ye ne zaman karar verileceğini belirlemek için. Muhasebe olmadan, 100 Bitmap nesnesinde referanslar ayırabilir ve bırakabilirsiniz; GC çalışmaz, çünkü bu nesneler çok küçüktür, ancak gerçekte şu anda çok fazla sayıda megabayt fiili tahsisleri temsil edebilirler. Bu tahsisatları Java yığınına karşı muhasebeleştirerek, çöp toplayıcısı, bellek kullanılmakta olduğunu düşündüğü gibi çalışacaktır.

Birçok yönden bunun bir uygulama detayı olduğunu unutmayın; Gelecekte değişebilecek olması muhtemeldir, ancak bu temel davranış, bitmap tahsislerini yönetmek için her ikisi de önemli özellikler olduğundan, bir şekilde kalır. vahşi dağıtımlar itibaren

+1

Hatta java yığın karşı bitmapler saymak telefonları, yerel malloc WAY 16 MB daha fazla tahsis edebilirsiniz. –

+10

İlk yorum yanlış, tüm telefonlar Dalvik yığın sınırına karşı bitmap ayırmalarını sayar. Unutulmaması gereken temel değişiklik, Android 3.0'dan itibaren, tahsislerin aslında Dalvik yığınında yapılmasıdır, dolayısıyla artık GC'nin gerektiği kadar agresif çalışmadığı durumlar ile uğraşmak zorunda kalmazsınız. – hackbod

+2

bu noktada haklısınız. Yine de, geri dönüştürülmüş bitmap'lerle uğraşmaya gelince GC gecikmektedir. Bir bitmap'i geri dönüştürdükten sonra GC'yi manuel olarak çalıştırmazsam (bir sonraki "yük" e, aslında diskten yüklemek yerine geri dönüştürülmüş bit eşlemin bir kopyasını döndürmek de dahil olmak üzere) manuel olarak çalıştırmadığım sürece tahmin edilemeyen davranışlar buldum. –

12

, ben aşağıdaki cihazları buldum: java yığın 16 MiB (bitmap'ler neredeyse sınırsızdır) ile sınırlamak

  • Cihazları. 16 MIB (java yığın + yerel bitmap depolama) Java öbek 24 MIB (bitmap'ler neredeyse sınırsız) sınırı
  • cihazlar sınırı
  • cihazlar.24 MIB (java yığın + yerel bitmap depolama) sınırlayan
  • cihazlar

24 MIB yüksek çöz cihazları olma eğilimindedir ve Runtime.getRuntime() ile tespit edilebilir. maxMemory(). Şu anda 32MiB cihazı var ve köklü telefonların bazıları varsayılan olarak 64MiB var. Önceden, neler olduğunu anlamaya çalışmak için birkaç kez kendimi karıştırdım. Bence tüm cihazlar bitmapleri yığın limitine sayar. Ama android filo hakkında kapsamlı genellemeler yapmak oldukça zor.

Bu Android'de çok kötü bir sorun ve çok kafa karıştırıcı. Bu sınır ve davranışları yetersiz belgelenmiştir, karmaşıktır ve son derece sezgisel değildir. Ayrıca cihazlar ve işletim sistemi sürümleri arasında farklılık gösterir ve bilinen bazı hatalar vardır. Problemin bir kısmı, sınırların kesin olmamasıdır - yığın parçalanması nedeniyle, OOM'a gerçek sınırın önünde iyi bir şekilde vurulacak ve bir mega veya iki tampondan muhafazakar bir şekilde bırakılmalıdır. Daha da kötüsü, java OOM istisnasını elde etmeden önce doğal bir segfault (Android'de% 100 bir hata) olan birkaç aygıtım var. yerel kilitlenme. Araştırmalarım hakkında daha fazla bilgi için, this post'a bakın. Aynı yazıda, kullanımın limite karşı nasıl ölçüleceğini ve çarpışmaların nasıl önleneceğini açıklarım.

Java yığınının boyutu Runtime.getRuntime(). TotalMemory(). Yerel bit eşlem deposunun boyutunu ölçmenin kolay bir yolu yoktur. Genel yerel yığın Debug.getNativeHeapAllocatedSize() ile ölçülebilir, ancak yalnızca bitmap'ler sınıra doğru sayılır (bence).

+0

Herkes kendi Android sürümünü yayınlayabildiğinden, yukarıda açıklananlar dahil olmak üzere yığın hafızasını sınırlamak için farklı politikalar uygulayan sürümlerin olabileceği konusunda oldukça inandırıcı görünmektedir. Örneğin, CyanogenMod, kullanıcıların yığın sınırını kendilerinin belirleyebilmelerini sağlar, bu yüzden neden açıkladığınız sınırlarla ilgili politikaları uygulayan bir işletim sistemi sürümü bulunamadığını anlamıyorum. Bu konuda herhangi bir resmi yönerge olup olmadığını bilmek isterim. Değilse, o zaman bu OS varyantlarının kaprislerine tabidiriz. – Carl

+0

@Carl.Anlatabildiğim kadarıyla, saf kaos. Genel olarak, modlar ve köklü telefonlar, tipik olarak 64M'ye kadar yığın sınırlarını arttırma eğilimindedir. Java yığın boyutunu çok ciddi bir şekilde sınırlama kararı, beyin-ölü geciktirildi ve korkunç kullanıcı deneyimleriyle sonuçlandı. –

+0

Bellek kullanımımıza daha yakından bakmamız için bizi geliştiriciler olarak zorluyor. Şu anda (tamamen yoğun bir arama işlemi nedeniyle) yığının tamamen üzerinde durması gereken çok büyük bir veri kümesine sahip bir uygulama geliştiriyorum ve orijinal String dizisi tabanlı uygulamam yalnızca bu veriler için 15 MB yığın aldı dizideki her String ref, 32 bayt veri alır). Birçok geçerli cihazın hala uyguladığı 24 MB limitine neredeyse girdikten sonra, tam olarak aynı bilgiyi tutmak için sadece 3.5MB alan özel bir veri yapısı tasarladım. Şimdi benim app 16MB limitli bir cihazda bile çalışacaktır. – Carl

-1

Bildirim dosyanızdaki yığın boyutunu android:largeheap="true" kullanarak artırabiliriz. Bu bazı problemlerinizi çözecektir.

+0

Kullanıcılarınızın pili hakkında düşünün ... Bellek ayırmalarındaki bazı hataları karşılamak için büyük bir yığın isteme, bir çözüm olamaz. – JuSchz

İlgili konular