اشکال‌زدایی زباله‌روبی ART

این صفحه نحوه اشکال‌زدایی کردن مشکلات عملکرد و صحت «جمع‌آوری داده‌های نامربوط» (GC) در «زمان اجرای Android» (ART) را شرح می‌دهد. این مقاله توضیح می‌دهد که چگونه از گزینه‌های درستی‌سنجی GC استفاده کنید، راه‌حل‌های مربوط به عدم موفقیت درستی‌سنجی GC را شناسایی کنید، و مشکلات عملکرد GC را اندازه‌گیری و برطرف کنید.

برای کار با ART، صفحه‌های این بخش ART و Dalvik و قالب اجرایی Dalvik را ببینید. برای دریافت کمک بیشتر در درستی‌سنجی رفتار برنامه، به درستی‌سنجی رفتار برنامه در زمان اجرای Android (ART) مراجعه کنید.

نمای کلی ART GC

‫ART چند طرح GC مختلف دارد که شامل اجرای جمع‌آوری‌کننده‌های مختلف زباله است. از Android 8 (Oreo) شروع می‌شود، طرح پیش‌فرض «کپی هم‌زمان» (CC) است. طرح GC دیگر Concurrent Mark Sweep (CMS) است.

برخی‌از ویژگی‌های اصلی «جمع‌آوری زباله کپی هم‌زمان» عبارت‌اند از:

  • ‫CC استفاده از تخصیص‌دهنده اشاره‌گر جهشی به نام RegionTLAB را فعال می‌کند. این کار یک بافر تخصیص محلی رشته‌ای (TLAB) به هر رشته برنامه اختصاص می‌دهد، که سپس می‌تواند اشیا را از TLAB خود با افزایش اشاره‌گر «بالا» بدون هیچ‌گونه همگام‌سازی تخصیص دهد.
  • CC یکپارچه‌سازی توده را با کپی کردن هم‌زمان اشیا بدون توقف رشته‌های برنامه انجام می‌دهد. این کار با کمک یک مانع خواندن انجام می‌شود که خواندن مرجع از پشته را بدون نیاز به هیچ‌گونه دخالت ازسوی توسعه‌دهنده برنامه رهگیری می‌کند.
  • ‫GC فقط یک توقف کوچک دارد که با توجه به اندازه پشته، در زمان ثابت است.
  • ‫CC در Android 10 و بالاتر به GC نسلی گسترش می‌یابد. این ویژگی امکان جمع‌آوری اشیاء جوان را فراهم می‌کند که اغلب با تلاش اندکی به‌سرعت غیرقابل‌دسترس می‌شوند. این کار با افزایش توان عملیاتی GC و به‌تأخیر انداختن قابل‌توجه نیاز به انجام GC پشته کامل کمک می‌کند.

‫GC دیگری که ART همچنان از آن پشتیبانی می‌کند CMS است. این «جمع‌آوری زباله» از فشرده‌سازی نیز پشتیبانی می‌کند، اما نه به‌طور هم‌زمان. تا زمانی که برنامه به پس‌زمینه نرود، از فشرده‌سازی اجتناب می‌شود. در این زمان، رشته‌های برنامه برای انجام فشرده‌سازی موقتاً متوقف می‌شوند. وقتی تخصیص شیء به‌دلیل تکه‌تکه شدن ناموفق باشد، فشرده‌سازی نیز ضروری می‌شود. در این مورد، برنامه ممکن است برای مدتی پاسخ‌گو نباشد.

ازآنجایی‌که CMS به‌ندرت فشرده‌سازی می‌کند، و بنابراین ممکن است اشیای آزاد پیوسته نباشند، از تخصیص‌دهنده مبتنی بر فهرست آزاد به نام RosAlloc استفاده می‌کند. هزینه تخصیص آن در مقایسه با RegionTLAB بالاتر است. درنهایت، به‌دلیل تکه‌تکه شدن داخلی، استفاده از حافظه برای پشته Java در CMS می‌تواند بیشتر از CC باشد.

گزینه‌های درستی‌سنجی و عملکرد GC

تغییر نوع GC

تولیدکنندگان تجهیزات اصلی می‌توانند نوع GC را تغییر دهند. فرایند تغییر شامل تنظیم متغیر محیط ART_USE_READ_BARRIER در زمان ساخت می‌شود. مقدار پیش‌فرض «درست» است که CC collector را فعال می‌کند زیرا از read-barrier استفاده می‌کند. برای «سیستم مدیریت محتوا»، این متغیر باید به‌طور صریح روی false تنظیم شود.

به‌طور پیش‌فرض، CC collector در Android 10 و بالاتر در حالت نسلی اجرا می‌شود. برای غیرفعال کردن حالت نسلی، می‌توان از آرگومان خط فرمان -Xgc:nogenerational_cc استفاده کرد. یا اینکه دارایی سیستم را می‌توان به این صورت تنظیم کرد:

adb shell setprop dalvik.vm.gctype nogenerational_cc
گردآورنده CMS همیشه در حالت نسلی اجرا می‌شود.

درستی‌سنجی پشته

درستی‌سنجی پشته احتمالاً مفیدترین گزینه GC برای اشکال‌زدایی خطاهای مربوط به GC یا خرابی پشته است. فعال کردن درستی‌سنجی پشته باعث می‌شود GC صحت پشته را در چند نقطه درطول فرایند جمع‌آوری زباله بررسی کند. درستی‌سنجی پشته همان گزینه‌هایی را دارد که نوع GC را تغییر می‌دهند. اگر فعال باشد، درستی‌سنجی پشته ریشه‌ها را درستی‌سنجی می‌کند و مطمئن می‌شود که اشیای قابل‌دسترس فقط به اشیای قابل‌دسترس دیگر ارجاع می‌دهند. درستی‌سنجی GC با ارسال مقادیر -Xgc زیر فعال می‌شود:

  • اگر فعال باشد، [no]preverify قبل‌از شروع GC، درستی‌سنجی پشته را انجام می‌دهد.
  • اگر فعال باشد، [no]presweepingverify درستی‌سنجی پشته را قبل‌از شروع فرایند جارو کردن جمع‌آوری زباله انجام می‌دهد.
  • اگر فعال باشد، [no]postverify درستی‌سنجی پشته را پس‌از پایان جارو کردن GC انجام می‌دهد.
  • ‫[no]preverify_rosalloc،‏ [no]postsweepingverify_rosalloc، و [no]postverify_rosalloc گزینه‌های GC اضافی هستند که فقط وضعیت حسابداری داخلی RosAlloc را درستی‌سنجی می‌کنند. بنابراین، این ویژگی‌ها فقط با گردآورنده «سیستم مدیریت محتوا» که از تخصیص‌دهنده RosAlloc استفاده می‌کند قابل‌اجرا هستند. مهم‌ترین چیزهایی که درستی‌سنجی می‌شوند این است که مقادیر جادویی با ثابت‌های موردانتظار مطابقت داشته باشند و همه بلوک‌های حافظه آزاد در نقشه free_page_runs_ ثبت شده باشند.

عملکرد

دو ابزار اصلی برای اندازه‌گیری عملکرد GC وجود دارد: داده‌ریزی‌های زمان‌بندی GC و Systrace. نسخه پیشرفته‌ای از Systrace نیز وجود دارد که Perfetto نامیده می‌شود. روش دیداری برای اندازه‌گیری مشکلات عملکرد GC استفاده از Systrace و Perfetto برای تعیین این است که کدام GCها باعث مکث‌های طولانی یا پیش‌دستی در رشته‌های برنامه می‌شوند. اگرچه «جمع‌آوری زباله» ART درطول زمان به‌طور قابل‌توجهی بهبود یافته است، عملکرد بد جهش‌دهنده (برای مثال تخصیص بیش‌ازحد) همچنان می‌تواند باعث مشکلات عملکرد شود

راهبرد مجموعه

CC GC با اجرای GC جوان یا GC پشته کامل جمع‌آوری می‌کند. در حالت ایده‌آل، GC جوان بیشتر اجرا می‌شود. «گردآورنده زباله» مجموعه‌های CC جوان را تا زمانی انجام می‌دهد که توان عملیاتی (محاسبه‌شده براساس بایت‌های آزادشده در ثانیه از مدت زمان GC) چرخه مجموعه تازه پایان‌یافته کمتر از توان عملیاتی میانگین مجموعه‌های CC کل پشته باشد. وقتی این اتفاق می‌افتد، به‌جای «جمع‌آوری زباله جوان»، «جمع‌آوری زباله هم‌زمان» با پشته کامل برای «جمع‌آوری زباله هم‌زمان» بعدی انتخاب می‌شود. پس‌از تکمیل جمع‌آوری پشته کامل، GC بعدی به CC جوان برمی‌گردد. یکی از عوامل کلیدی که باعث می‌شود این استراتژی کار کند این است که CC جوان پس‌از تکمیل، حد ردپای پشته را تنظیم نمی‌کند. این امر باعث می‌شود که CC جوان بیشتر و بیشتر اتفاق بیفتد تا زمانی که توان عملیاتی کمتر از CC پشته کامل شود، که درنهایت باعث رشد پشته می‌شود.

برای دریافت اطلاعات عملکرد GC، از SIGQUIT استفاده کنید

برای دریافت زمان‌بندی عملکرد GC برای برنامه‌ها، SIGQUIT را به برنامه‌هایی که ازقبل درحال اجرا هستند ارسال کنید یا -XX:DumpGCPerformanceOnShutdown را هنگام شروع برنامه خط فرمان به dalvikvm ارسال کنید. وقتی برنامه‌ای سیگنال درخواست ANR‏ (SIGQUIT) را دریافت می‌کند، اطلاعات مربوط به قفل‌ها، پشته‌های رشته، و عملکرد GC را تخلیه می‌کند.

برای دریافت تخلیه‌های زمان‌بندی GC، از این استفاده کنید:

adb shell kill -s QUIT PID

این کار فایلی (با تاریخ و زمان در نام آن، مثلاً anr_2020-07-13-19-23-39-817) در /data/anr/ ایجاد می‌کند. این فایل حاوی چند تخلیه ANR و همچنین زمان‌بندی‌های GC است. با جستجوی Dumping cumulative Gc timings می‌توانید زمان‌بندی‌های GC را پیدا کنید. این زمان‌بندی‌ها چند مورد جالب را نشان می‌دهد، ازجمله اطلاعات هیستوگرام برای هر نوع GC و مراحل و وقفه‌های آن. توقف‌ها معمولاً مهم‌تر هستند که به آن‌ها نگاه کنید. برای مثال:

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

این نشان می‌دهد که میانگین توقف ۱٫۸۳ میلی‌ثانیه بوده است که باید به‌اندازه کافی کم باشد تا باعث ازدست رفتن قاب در اکثر برنامه‌ها نشود و نباید نگران آن بود.

یکی دیگر از زمینه‌های موردعلاقه، زمان تعلیق است که اندازه‌گیری می‌کند چقدر طول می‌کشد تا یک رشته پس‌از درخواست GC برای تعلیق، به نقطه تعلیق برسد. این زمان در توقف‌های GC لحاظ می‌شود، بنابراین برای تعیین اینکه آیا توقف‌های طولانی ناشی از کند بودن GC است یا تعلیق کند رشته مفید است. در اینجا نمونه‌ای از زمان عادی برای تعلیق کردن در Nexus 5 آورده شده است:

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

بخش‌های جالب دیگری نیز وجود دارد، ازجمله کل زمان صرف‌شده و توان عملیاتی GC. نمونه‌ها:

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

در اینجا نمونه‌ای از نحوه تخلیه زمان‌بندی‌های GC یک برنامه درحال اجرا آورده شده است:

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

در این نقطه، زمان‌بندی‌های GC درون anr_2020-07-13-19-23-39-817 است. در اینجا نمونه‌ای از خروجی Google Maps آورده شده است:

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

موارد مختلفی می‌تواند باعث ازکارافتادن در ART شود. خرابی‌هایی که هنگام خواندن یا نوشتن در فیلدهای شیء رخ می‌دهند ممکن است نشان‌دهنده خرابی پشته باشند. اگر ‫GC هنگام اجرا ازکار بیفتد، می‌تواند نشان‌دهنده خرابی پشته نیز باشد. رایج‌ترین دلیل خرابی پشته، کد برنامه نادرست است. خوشبختانه، ابزارهایی برای اشکال‌زدایی خرابی‌های مربوط به GC و پشته وجود دارد، ازجمله گزینه‌های درستی‌سنجی پشته که در بالا مشخص شده است و CheckJNI.

CheckJNI

‫CheckJNI حالت افزودن بررسی‌های JNI برای درستی‌سنجی رفتار برنامه است؛ این بررسی‌ها به‌طور پیش‌فرض به‌دلایل عملکرد فعال نیستند. این بررسی‌ها چند خطا را که می‌تواند باعث خرابی توده شود، مانند استفاده از ارجاع‌های محلی و سراسری نامعتبر/قدیمی، شناسایی می‌کند. برای فعال کردن CheckJNI:

adb shell setprop dalvik.vm.checkjni true

حالت forcecopy در CheckJNI برای شناسایی نوشتن‌های فراتر از انتهای ناحیه‌های آرایه مفید است. وقتی فعال باشد، forcecopy باعث می‌شود توابع JNI دسترسی به آرایه نسخه‌هایی با مناطق قرمز برگردانند. منطقه قرمز ناحیه‌ای در ابتدا/انتهای اشاره‌گر برگردانده‌شده است که مقدار خاصی دارد و هنگام انتشار آرایه تأیید می‌شود. اگر مقادیر در منطقه قرمز با آنچه انتظار می‌رود مطابقت نداشته باشد، سرریز یا کمبود بافر رخ داده است. این کار باعث می‌شود CheckJNI متوقف شود. برای فعال کردن حالت forcecopy:

adb shell setprop dalvik.vm.jniopts forcecopy

مثالی از خطایی که CheckJNI باید آن را بگیرد نوشتن فراتر از انتهای آرایه به‌دست‌آمده از GetPrimitiveArrayCritical است. این عملیات می‌تواند پشته جاوا را خراب کند. اگر نوشتن در منطقه قرمز CheckJNI باشد، CheckJNI مشکل را هنگام فراخوانی ReleasePrimitiveArrayCritical مربوطه تشخیص می‌دهد. درغیراین‌صورت، نوشتن باعث خراب شدن برخی‌از اشیای تصادفی در انباشت Java می‌شود و می‌تواند باعث ازکارافتادن GC در آینده شود. اگر حافظه خراب یک فیلد مرجع باشد، GC ممکن است خطا را بگیرد و خطای Tried to mark <ptr> not contained by any spaces را چاپ کند.

این خطا زمانی رخ می‌دهد که GC تلاش می‌کند شیئی را علامت‌گذاری کند که نمی‌تواند فضایی برای آن پیدا کند. پس‌از ناموفق بودن این بررسی، GC ریشه‌ها را پیمایش می‌کند و سعی می‌کند ببیند آیا شیء نامعتبر ریشه است یا نه. از اینجا، دو گزینه وجود دارد: شیء یک شیء ریشه یا غیر ریشه است.

نمونه ریشه نامعتبر است

درصورتی‌که شیء ریشه نامعتبر باشد، اطلاعات مفید زیر را چاپ می‌کند: 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

در این مورد، vreg=1 در com.google.gwt.collections.JavaReadableJsArray.get باید حاوی مرجع پشته باشد، اما حاوی اشاره‌گر نامعتبر نشانی 0x2 است. این ریشه نامعتبر است. برای اشکال‌زدایی این مشکل، از oatdump در فایل oat استفاده کنید و روش دارای ریشه نامعتبر را بررسی کنید. در این مورد، خطا یک اشکال در زیرینه x86 کامپایلر بود. در اینجا فهرست تغییراتی که آن را اصلاح کرده است ارائه شده است: https://android-review.googlesource.com/#/c/133932/

نمونه شیء خراب

اگر شیء ریشه نباشد، برونداد مشابه موارد زیر چاپ می‌شود:

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

وقتی خرابی پشته ریشه نامعتبر نباشد، اشکال‌زدایی دشوار است. این پیام خطا نشان می‌دهد که حداقل یک شیء در پشته وجود داشته است که به شیء نامعتبر اشاره می‌کرده است.