ART atık toplama işleminde hata ayıklama

Bu sayfada, Android Runtime (ART) çöp toplama (GC) doğruluğu ve performans sorunlarının nasıl hata ayıklandığı açıklanmaktadır. Bu makalede, GC doğrulama seçeneklerinin nasıl kullanılacağı, GC doğrulama hatalarına yönelik çözümlerin nasıl belirleneceği ve GC performans sorunlarının nasıl ölçüleceği ve ele alınacağı açıklanmaktadır.

ART ile çalışmak için bu ART ve Dalvik bölümündeki sayfalara ve Dalvik yürütülebilir biçimine göz atın. Uygulama davranışını doğrulamayla ilgili daha fazla yardım için Android çalışma zamanında (ART) uygulama davranışını doğrulama başlıklı makaleyi inceleyin.

ART GC'ye genel bakış

ART, farklı çöp toplayıcıları çalıştırmaktan oluşan birkaç farklı GC planına sahiptir. Android 8 (Oreo) ve sonraki sürümlerde varsayılan plan eşzamanlı kopyalama (CC) olur. Diğer GC planı, eşzamanlı işaretleme ve temizleme (CMS) planıdır.

Eşzamanlı Kopyalama GC'nin temel özelliklerinden bazıları şunlardır:

  • CC, RegionTLAB adlı bir artış işaretçisi ayırıcısının kullanılmasını sağlar. Bu işlem, her uygulama iş parçacığına bir iş parçacığı yerel atama arabelleği (TLAB) ayırır. Bu arabellek, daha sonra herhangi bir senkronizasyon olmadan "üst" işaretçiyi artırarak TLAB'sından nesneler ayırabilir.
  • CC, uygulama iş parçacıklarını duraklatmadan nesneleri eşzamanlı olarak kopyalayarak yığın birleştirme işlemini gerçekleştirir. Bu, uygulama geliştiricisinin müdahalesine gerek kalmadan yığıntan referans okumalarını engelleyen bir okuma bariyeri yardımıyla elde edilir.
  • GC'de yalnızca bir küçük duraklatma olur ve bu duraklatma, yığın boyutuna göre zaman içinde sabit kalır.
  • CC, Android 10 ve sonraki sürümlerde nesil GC olarak genişletilmiştir. Genellikle oldukça hızlı bir şekilde erişilemez hale gelen genç nesnelerin az çabayla toplanmasını sağlar. Bu, GC verimini artırarak ve tam yığın GC gerçekleştirme ihtiyacını önemli ölçüde geciktirerek yardımcı olur.

ART'ın hâlâ desteklediği diğer GC, İYS'dir. Bu GC, sıkıştırmayı da destekler ancak eşzamanlı olarak değil. Uygulama arka plana geçene kadar sıkıştırma yapılmaz. Bu durumda, sıkıştırma işlemini gerçekleştirmek için uygulama iş parçacıkları duraklatılır. Sıkıştırma, bir nesne tahsisi parçalanma nedeniyle başarısız olduğunda da gerekli olur. Bu durumda uygulama bir süre boyunca yanıt vermeyebilir.

İçerik yönetim sistemi nadiren sıkıştırıldığından ve bu nedenle boş nesneler bitişik olmayabileceğinden, RosAlloc adlı boş liste tabanlı bir ayırıcı kullanır. RegionTLAB'ye kıyasla daha yüksek bir ayırma maliyetine sahiptir. Son olarak, dahili parçalanma nedeniyle İYS'de Java yığınının bellek kullanımı CC'ye kıyasla daha yüksek olabilir.

GC doğrulaması ve performans seçenekleri

GC türünü değiştirme

OEM'ler GC türünü değiştirebilir. Değişiklik süreci, derleme sırasında ART_USE_READ_BARRIER ortam değişkeninin ayarlanmasını içerir. Varsayılan değer true (doğru) olduğundan CC toplayıcısı, okuma bariyeri kullandığı için etkinleştirilir. İYS için bu değişken açıkça false olarak ayarlanmalıdır.

CC toplayıcı, Android 10 ve sonraki sürümlerde varsayılan olarak nesil modunda çalışır. Nesil oluşturma modunu devre dışı bırakmak için -Xgc:nogenerational_cc komut satırı bağımsız değişkeni kullanılabilir. Alternatif olarak, sistem özelliği aşağıdaki gibi ayarlanabilir:

adb shell setprop dalvik.vm.gctype nogenerational_cc
İYS toplayıcısı her zaman nesil modunda çalışır.

Yığını doğrulama

Yığın doğrulaması, GC ile ilgili hataları veya yığın bozulmasını gidermek için muhtemelen en yararlı GC seçeneğidir. Yığın doğrulamasının etkinleştirilmesi, GC'nin çöp toplama işlemi sırasında birkaç noktada yığının doğruluğunu kontrol etmesine neden olur. Yığın doğrulama, GC türünü değiştiren seçeneklerle aynı seçenekleri paylaşır. Etkinleştirildiğinde yığın doğrulaması kökleri doğrular ve erişilebilir nesnelerin yalnızca diğer erişilebilir nesnelere referans vermesini sağlar. GC doğrulaması, aşağıdaki -Xgc değerlerini ileterek etkinleştirilir:

  • Etkinleştirilirse [no]preverify, GC'yi başlatmadan önce yığın doğrulaması yapar.
  • Etkinleştirilirse [no]presweepingverify, çöp toplayıcı süpürme işlemini başlatmadan önce yığın doğrulaması yapar.
  • Etkinleştirilirse [no]postverify, GC süpürmeyi tamamladıktan sonra yığın doğrulaması yapar.
  • [no]preverify_rosalloc, [no]postsweepingverify_rosalloc ve [no]postverify_rosalloc, yalnızca RosAlloc'un dahili muhasebesinin durumunu doğrulayan ek GC seçenekleridir. Bu nedenle, yalnızca RosAlloc ayırıcıyı kullanan İYS toplayıcısı ile geçerlidir. Doğrulanan temel noktalar, sihirli değerlerin beklenen sabitlerle eşleştiği ve tüm boş bellek bloklarının free_page_runs_ haritasına kaydedildiğidir.

Performans

GC performansını ölçmek için kullanılan iki ana araç vardır: GC zamanlama dökümleri ve Systrace. Systrace'in Perfetto adlı gelişmiş bir sürümü de vardır. GC performans sorunlarını ölçmenin görsel yolu, hangi GC'lerin uzun duraksamalara veya uygulama iş parçacıklarını öncelikli olarak çalıştırmaya neden olduğunu belirlemek için Systrace ve Perfetto'yu kullanmaktır. ART GC zaman içinde önemli ölçüde iyileşmiş olsa da aşırı tahsis gibi kötü değiştirici davranışları performans sorunlarına neden olmaya devam edebilir.

Koleksiyon stratejisi

CC GC, genç bir GC veya tam yığın GC çalıştırarak toplar. İdeal olarak genç GC daha sık çalıştırılır. GC, yeni CC koleksiyonlarını, yeni biten koleksiyon döngüsünün veri akışı (GC süresi boyunca serbest bırakılan bayt sayısı/saniye ile hesaplanır) tam yığın CC koleksiyonlarının ortalama veri akışından daha az olana kadar yapar. Bu durumda, sonraki eşzamanlı GC için genç CC yerine tam yığın CC seçilir. Tam yığın toplama işlemi tamamlandıktan sonra bir sonraki GC, genç CC'ye geri döner. Bu stratejinin işe yaramasını sağlayan önemli faktörlerden biri, genç CC'nin tamamlandıktan sonra yığın ayak izi sınırını ayarlamaması. Bu durum, aktarım hızı tam yığın CC'den daha düşük olana kadar genç CC'nin daha sık gerçekleşmesine neden olur ve yığının büyümesine yol açar.

GC performans bilgilerini almak için SIGQUIT'i kullanma

Uygulamaların GC performans zamanlamalarını almak için SIGQUIT'ü zaten çalışan uygulamalara gönderin veya bir komut satırı programını başlatırken -XX:DumpGCPerformanceOnShutdowndalvikvm'ye iletin. Bir uygulama ANR istek sinyalini (SIGQUIT) aldığında kilitleri, iş parçacığı yığınları ve GC performansıyla ilgili bilgileri döker.

GC zamanlama dökümlerini almak için şunları kullanın:

adb shell kill -s QUIT PID

Bu işlem, /data/anr/ içinde bir dosya (adında tarih ve saat bulunan anr_2020-07-13-19-23-39-817 gibi) oluşturur. Bu dosya, GC zamanlamaları ve bazı ANR dökümleri içerir. Kümülatif Gc zamanlamaları dökümü'nü arayarak GC zamanlamalarını bulabilirsiniz. Bu zamanlamalarda, her GC türünün aşamaları ve duraklamaları için histogram bilgileri de dahil olmak üzere ilginizi çekebilecek birkaç şey gösterilir. Genellikle duraklamalar daha önemlidir. Örnek:

young concurrent copying paused:	Sum: 5.491ms 99% C.I. 1.464ms-2.133ms Avg: 1.830ms Max: 2.133ms

Bu, ortalama duraklatmanın 1,83 ms olduğunu gösterir.Bu değer, çoğu uygulamada kare atlamasına neden olmayacak kadar düşüktür ve endişelenmeniz gereken bir durum değildir.

İlgi çekici bir diğer alan da askıya alma süresidir. Bu süre, GC'nin bir iş parçacığının askıya alınmasını istemesinden sonra iş parçacığının bir askıya alma noktasına ulaşması için geçen süreyi ölçer. Bu süre, GC duraklamaları içerisine dahil edilir. Bu nedenle, uzun duraklamaların GC'nin yavaşlamasından mı yoksa iş parçacığının yavaşça askıya alınmasından mı kaynaklandığını belirlemek yararlıdır. Nexus 5'te askıya alma işleminin normal süresini gösteren bir örnek:

suspend all histogram:	Sum: 1.513ms 99% C.I. 3us-546.560us Avg: 47.281us Max: 601us

Toplam harcanan süre ve GC veri akışı da dahil olmak üzere ilgi çekici başka alanlar da vardır. Örnekler:

Total time spent in GC: 502.251ms
Mean GC size throughput: 92MB/s
Mean GC object throughput: 1.54702e+06 objects/s

Aşağıda, halihazırda çalışan bir uygulamanın GC zamanlamalarına nasıl döküm alınacağına dair bir örnek verilmiştir:

adb shell kill -s QUIT PID
adb pull /data/anr/anr_2020-07-13-19-23-39-817

Bu noktada GC zamanlamaları anr_2020-07-13-19-23-39-817 içindedir. Aşağıda Google Haritalar'dan örnek bir çıkış verilmiştir:

Start Dumping histograms for 2195 iterations for concurrent copying
MarkingPhase:   Sum: 258.127s 99% C.I. 58.854ms-352.575ms Avg: 117.651ms Max: 641.940ms
ScanCardsForSpace:      Sum: 85.966s 99% C.I. 15.121ms-112.080ms Avg: 39.164ms Max: 662.555ms
ScanImmuneSpaces:       Sum: 79.066s 99% C.I. 7.614ms-57.658ms Avg: 18.014ms Max: 546.276ms
ProcessMarkStack:       Sum: 49.308s 99% C.I. 6.439ms-81.640ms Avg: 22.464ms Max: 638.448ms
ClearFromSpace: Sum: 35.068s 99% C.I. 6.522ms-40.040ms Avg: 15.976ms Max: 633.665ms
SweepSystemWeaks:       Sum: 14.209s 99% C.I. 3.224ms-15.210ms Avg: 6.473ms Max: 201.738ms
CaptureThreadRootsForMarking:   Sum: 11.067s 99% C.I. 0.835ms-13.902ms Avg: 5.044ms Max: 25.565ms
VisitConcurrentRoots:   Sum: 8.588s 99% C.I. 1.260ms-8.547ms Avg: 1.956ms Max: 231.593ms
ProcessReferences:      Sum: 7.868s 99% C.I. 0.002ms-8.336ms Avg: 1.792ms Max: 17.376ms
EnqueueFinalizerReferences:     Sum: 3.976s 99% C.I. 0.691ms-8.005ms Avg: 1.811ms Max: 16.540ms
GrayAllDirtyImmuneObjects:      Sum: 3.721s 99% C.I. 0.622ms-6.702ms Avg: 1.695ms Max: 14.893ms
SweepLargeObjects:      Sum: 3.202s 99% C.I. 0.032ms-6.388ms Avg: 1.458ms Max: 549.851ms
FlipOtherThreads:       Sum: 2.265s 99% C.I. 0.487ms-3.702ms Avg: 1.031ms Max: 6.327ms
VisitNonThreadRoots:    Sum: 1.883s 99% C.I. 45us-3207.333us Avg: 429.210us Max: 27524us
InitializePhase:        Sum: 1.624s 99% C.I. 231.171us-2751.250us Avg: 740.220us Max: 6961us
ForwardSoftReferences:  Sum: 1.071s 99% C.I. 215.113us-2175.625us Avg: 488.362us Max: 7441us
ReclaimPhase:   Sum: 490.854ms 99% C.I. 32.029us-6373.807us Avg: 223.623us Max: 362851us
EmptyRBMarkBitStack:    Sum: 479.736ms 99% C.I. 11us-3202.500us Avg: 218.558us Max: 13652us
CopyingPhase:   Sum: 399.163ms 99% C.I. 24us-4602.500us Avg: 181.851us Max: 22865us
ThreadListFlip: Sum: 295.609ms 99% C.I. 15us-2134.999us Avg: 134.673us Max: 13578us
ResumeRunnableThreads:  Sum: 238.329ms 99% C.I. 5us-2351.250us Avg: 108.578us Max: 10539us
ResumeOtherThreads:     Sum: 207.915ms 99% C.I. 1.072us-3602.499us Avg: 94.722us Max: 14179us
RecordFree:     Sum: 188.009ms 99% C.I. 64us-312.812us Avg: 85.653us Max: 2709us
MarkZygoteLargeObjects: Sum: 133.301ms 99% C.I. 12us-734.999us Avg: 60.729us Max: 10169us
MarkStackAsLive:        Sum: 127.554ms 99% C.I. 13us-417.083us Avg: 58.111us Max: 1728us
FlipThreadRoots:        Sum: 126.119ms 99% C.I. 1.028us-3202.499us Avg: 57.457us Max: 11412us
SweepAllocSpace:        Sum: 117.761ms 99% C.I. 24us-400.624us Avg: 53.649us Max: 1541us
SwapBitmaps:    Sum: 56.301ms 99% C.I. 10us-125.312us Avg: 25.649us Max: 1475us
(Paused)GrayAllNewlyDirtyImmuneObjects: Sum: 33.047ms 99% C.I. 9us-49.931us Avg: 15.055us Max: 72us
(Paused)SetFromSpace:   Sum: 11.651ms 99% C.I. 2us-49.772us Avg: 5.307us Max: 71us
(Paused)FlipCallback:   Sum: 7.693ms 99% C.I. 2us-32us Avg: 3.504us Max: 32us
(Paused)ClearCards:     Sum: 6.371ms 99% C.I. 250ns-49753ns Avg: 207ns Max: 188000ns
Sweep:  Sum: 5.793ms 99% C.I. 1us-49.818us Avg: 2.639us Max: 93us
UnBindBitmaps:  Sum: 5.255ms 99% C.I. 1us-31us Avg: 2.394us Max: 31us
Done Dumping histograms
concurrent copying paused:      Sum: 315.249ms 99% C.I. 49us-1378.125us Avg: 143.621us Max: 7722us
concurrent copying freed-bytes: Avg: 34MB Max: 54MB Min: 2062KB
Freed-bytes histogram: 0:4,5120:5,10240:19,15360:69,20480:167,25600:364,30720:529,35840:405,40960:284,46080:311,51200:38
concurrent copying total time: 569.947s mean time: 259.657ms
concurrent copying freed: 1453160493 objects with total size 74GB
concurrent copying throughput: 2.54964e+06/s / 134MB/s  per cpu-time: 157655668/s / 150MB/s
Average major GC reclaim bytes ratio 0.486928 over 2195 GC cycles
Average major GC copied live bytes ratio 0.0894662 over 2199 major GCs
Cumulative bytes moved 6586367960
Cumulative objects moved 127490240
Peak regions allocated 376 (94MB) / 2048 (512MB)
Start Dumping histograms for 685 iterations for young concurrent copying
ScanCardsForSpace:      Sum: 26.288s 99% C.I. 8.617ms-77.759ms Avg: 38.377ms Max: 432.991ms
ProcessMarkStack:       Sum: 21.829s 99% C.I. 2.116ms-71.119ms Avg: 31.868ms Max: 98.679ms
ClearFromSpace: Sum: 19.420s 99% C.I. 5.480ms-50.293ms Avg: 28.351ms Max: 507.330ms
ScanImmuneSpaces:       Sum: 9.968s 99% C.I. 8.155ms-30.639ms Avg: 14.552ms Max: 46.676ms
SweepSystemWeaks:       Sum: 6.741s 99% C.I. 3.655ms-14.715ms Avg: 9.841ms Max: 22.142ms
GrayAllDirtyImmuneObjects:      Sum: 4.466s 99% C.I. 0.584ms-14.315ms Avg: 6.519ms Max: 24.355ms
FlipOtherThreads:       Sum: 3.672s 99% C.I. 0.631ms-16.630ms Avg: 5.361ms Max: 18.513ms
ProcessReferences:      Sum: 2.806s 99% C.I. 0.001ms-9.459ms Avg: 2.048ms Max: 11.951ms
EnqueueFinalizerReferences:     Sum: 1.857s 99% C.I. 0.424ms-8.609ms Avg: 2.711ms Max: 24.063ms
VisitConcurrentRoots:   Sum: 1.094s 99% C.I. 1.306ms-5.357ms Avg: 1.598ms Max: 6.831ms
SweepArray:     Sum: 711.032ms 99% C.I. 0.022ms-3.502ms Avg: 1.038ms Max: 7.307ms
InitializePhase:        Sum: 667.346ms 99% C.I. 303us-2643.749us Avg: 974.227us Max: 3199us
VisitNonThreadRoots:    Sum: 388.145ms 99% C.I. 103.911us-1385.833us Avg: 566.635us Max: 5374us
ThreadListFlip: Sum: 202.730ms 99% C.I. 18us-2414.999us Avg: 295.956us Max: 6780us
EmptyRBMarkBitStack:    Sum: 132.934ms 99% C.I. 8us-1757.499us Avg: 194.064us Max: 8495us
ResumeRunnableThreads:  Sum: 109.593ms 99% C.I. 6us-4719.999us Avg: 159.989us Max: 11106us
ResumeOtherThreads:     Sum: 86.733ms 99% C.I. 3us-4114.999us Avg: 126.617us Max: 19332us
ForwardSoftReferences:  Sum: 69.686ms 99% C.I. 14us-2014.999us Avg: 101.731us Max: 4723us
RecordFree:     Sum: 58.889ms 99% C.I. 0.500us-185.833us Avg: 42.984us Max: 769us
FlipThreadRoots:        Sum: 58.540ms 99% C.I. 1.034us-4314.999us Avg: 85.459us Max: 10224us
CopyingPhase:   Sum: 52.227ms 99% C.I. 26us-728.749us Avg: 76.243us Max: 2060us
ReclaimPhase:   Sum: 37.207ms 99% C.I. 7us-2322.499us Avg: 54.316us Max: 3826us
(Paused)GrayAllNewlyDirtyImmuneObjects: Sum: 23.859ms 99% C.I. 11us-98.917us Avg: 34.830us Max: 128us
FreeList:       Sum: 20.376ms 99% C.I. 2us-188.875us Avg: 29.573us Max: 998us
MarkZygoteLargeObjects: Sum: 18.970ms 99% C.I. 4us-115.749us Avg: 27.693us Max: 122us
(Paused)SetFromSpace:   Sum: 12.331ms 99% C.I. 3us-94.226us Avg: 18.001us Max: 109us
SwapBitmaps:    Sum: 11.761ms 99% C.I. 5us-49.968us Avg: 17.169us Max: 67us
ResetStack:     Sum: 4.317ms 99% C.I. 1us-64.374us Avg: 6.302us Max: 190us
UnBindBitmaps:  Sum: 3.803ms 99% C.I. 4us-49.822us Avg: 5.551us Max: 70us
(Paused)ClearCards:     Sum: 3.336ms 99% C.I. 250ns-7000ns Avg: 347ns Max: 7000ns
(Paused)FlipCallback:   Sum: 3.082ms 99% C.I. 1us-30us Avg: 4.499us Max: 30us
Done Dumping histograms
young concurrent copying paused:        Sum: 229.314ms 99% C.I. 37us-2287.499us Avg: 334.764us Max: 6850us
young concurrent copying freed-bytes: Avg: 44MB Max: 50MB Min: 9132KB
Freed-bytes histogram: 5120:1,15360:1,20480:6,25600:1,30720:1,35840:9,40960:235,46080:427,51200:4
young concurrent copying total time: 100.823s mean time: 147.187ms
young concurrent copying freed: 519927309 objects with total size 30GB
young concurrent copying throughput: 5.15683e+06/s / 304MB/s  per cpu-time: 333152554/s / 317MB/s
Average minor GC reclaim bytes ratio 0.52381 over 685 GC cycles
Average minor GC copied live bytes ratio 0.0512109 over 685 minor GCs
Cumulative bytes moved 1542000944
Cumulative objects moved 28393168
Peak regions allocated 376 (94MB) / 2048 (512MB)
Total time spent in GC: 670.771s
Mean GC size throughput: 159MB/s per cpu-time: 177MB/s
Mean GC object throughput: 2.94152e+06 objects/s
Total number of allocations 1974199562
Total bytes allocated 104GB
Total bytes freed 104GB
Free memory 10MB
Free memory until GC 10MB
Free memory until OOME 442MB
Total memory 80MB
Max memory 512MB
Zygote space size 2780KB
Total mutator paused time: 544.563ms
Total time waiting for GC to complete: 117.494ms
Total GC count: 2880
Total GC time: 670.771s
Total blocking GC count: 1
Total blocking GC time: 86.373ms
Histogram of GC count per 10000 ms: 0:259879,1:2828,2:24,3:1
Histogram of blocking GC count per 10000 ms: 0:262731,1:1
Native bytes total: 30599192 registered: 8947416
Total native bytes at last GC: 30344912

GC doğruluğu sorunlarını analiz etme araçları

ART'ta kilitlenmelere yol açabilecek çeşitli durumlar vardır. Nesne alanlarına okuma veya yazma sırasında meydana gelen kilitlenmeler, yığın bozulmasını gösterebilir. GC çalışırken kilitleniyorsa yığın bozulmasına da işaret ediyor olabilir. Yığın bozulmasının en yaygın nedeni yanlış uygulama kodudur. Neyse ki, yukarıda belirtilen yığın doğrulama seçenekleri ve CheckJNI dahil olmak üzere GC ve yığınla ilgili kilitlenmelerde hata ayıklamanızı sağlayacak araçlar mevcuttur.

CheckJNI

CheckJNI, uygulama davranışını doğrulamak için JNI kontrolleri ekleyen bir moddur. Bu kontroller, performans nedeniyle varsayılan olarak etkin değildir. Kontroller, geçersiz/güncel olmayan yerel ve genel referansların kullanılması gibi yığın bozulmasına neden olabilecek birkaç hatayı yakalar. CheckJNI'yi etkinleştirmek için:

adb shell setprop dalvik.vm.checkjni true

CheckJNI'nin forcecopy modu, dizi bölgelerinin sonunu aşan yazma işlemlerini algılamak için kullanışlıdır. Zorunlu kopyalama etkinleştirildiğinde dizi erişim JNI işlevleri, kırmızı bölgeler içeren kopyalar döndürür. Kırmızı bölge, döndürülen işaretçinin sonunda/başında bulunan ve özel bir değere sahip olan, dizi serbest bırakıldığında doğrulanan bir bölgedir. Kırmızı bölgedeki değerler beklenenle eşleşmiyorsa arabellek taşması veya yetersizliği meydana gelmiştir. Bu durum, CheckJNI'nin iptal edilmesine neden olur. Zorunlu kopyalama modunu etkinleştirmek için:

adb shell setprop dalvik.vm.jniopts forcecopy

CheckJNI'nin yakalaması gereken bir hata örneği, GetPrimitiveArrayCritical kaynağından elde edilen bir dizinin sonunun ötesine yazmadır. Bu işlem Java yığınını bozabilir. Yazma işlemi CheckJNI kırmızı bölgesi içindeyse ilgili ReleasePrimitiveArrayCritical çağrıldığında CheckJNI sorunu yakalar. Aksi takdirde, yazma işlemi Java yığınındaki rastgele bir nesneyi bozar ve gelecekte GC kilitlenmesine neden olabilir. Bozuk bellek bir referans alanıysa GC hatayı yakalayabilir ve <ptr> değerinin boşluk içermediğini işaretlemeye çalıştı hatasını basabilir.

Bu hata, GC için yer bulamadığı bir nesneyi işaretlemeye çalışırken ortaya çıkar. Bu denetim başarısız olduktan sonra GC, kökleri tarar ve geçersiz nesnenin kök olup olmadığını anlamaya çalışır. Burada iki seçenek vardır: Öğe, kök öğe veya kök olmayan bir öğedir.

Geçersiz kök örneği

Nesne geçersiz bir kök olduğunda bazı yararlı bilgiler yazdırır: art E 5955 5955 art/runtime/gc/collector/mark_sweep.cc:383] Tried to mark 0x2 not contained by any spaces

art E  5955  5955 art/runtime/gc/collector/mark_sweep.cc:384] Attempting see if
it's a bad root
art E  5955  5955 art/runtime/gc/collector/mark_sweep.cc:485] Found invalid
root: 0x2
art E  5955  5955 art/runtime/gc/collector/mark_sweep.cc:486]
Type=RootJavaFrame thread_id=1 location=Visiting method 'java.lang.Object
com.google.gwt.collections.JavaReadableJsArray.get(int)' at dex PC 0x0002
(native PC 0xf19609d9) vreg=1

Bu durumda, com.google.gwt.collections.JavaReadableJsArray.get içindeki vreg=1 bir yığın referansı içermesi gerekir ancak 0x2 adresinin geçersiz bir işaretçisini içerir. Bu geçersiz bir köktür. Bu sorunun hata ayıklama işlemini yapmak için oat dosyasında oatdump'ü kullanın ve geçersiz köke sahip yönteme bakın. Bu durumda, hatanın x86 arka ucundaki bir derleyici hatası olduğu ortaya çıktı. Bu sorunu gideren değişiklik listesi: https://android-review.googlesource.com/#/c/133932/

Bozuk nesne örneği

Nesne kök değilse aşağıdakine benzer bir çıkış yazdırılır:

01-15 12:38:00.196  1217  1238 E art     : Attempting see if it's a bad root
01-15 12:38:00.196  1217  1238 F art     :
art/runtime/gc/collector/mark_sweep.cc:381] Can't mark invalid object

Yığın bozulması geçersiz bir kök olmadığında hata ayıklama zordur. Bu hata mesajı, yığınta geçersiz nesneyi işaret eden en az bir nesne olduğunu gösterir.