একটি গাদা ডাম্প ক্যাপচার

আপনার অ্যাপের কোন অবজেক্টগুলো ক্যাপচারের সময় মেমরি ব্যবহার করছে তা দেখতে এবং মেমরি লিক বা মেমরি অ্যালোকেশন আচরণ শনাক্ত করতে একটি হিপ ডাম্প ক্যাপচার করুন, যা অ্যাপ আটকে যাওয়া, থেমে যাওয়া এবং এমনকি ক্র্যাশের কারণ হতে পারে। দীর্ঘ সময় ধরে ইউজার সেশন চলার পর হিপ ডাম্প নেওয়া বিশেষভাবে সহায়ক, কারণ তখন এমন অবজেক্টও মেমরিতে থেকে যেতে পারে যা আর সেখানে থাকার কথা নয়।

এই পৃষ্ঠায় অ্যান্ড্রয়েড স্টুডিও দ্বারা প্রদত্ত হিপ ডাম্প সংগ্রহ ও বিশ্লেষণের টুলগুলোর বর্ণনা দেওয়া হয়েছে। বিকল্পভাবে, আপনি কমান্ড লাইন থেকে dumpsys ব্যবহার করে আপনার অ্যাপের মেমরি পরীক্ষা করতে পারেন এবং Logcat-এ গার্বেজ কালেকশন (GC) ইভেন্টগুলোও দেখতে পারেন

কেন আপনার অ্যাপ মেমরি প্রোফাইল করা উচিত

অ্যান্ড্রয়েড একটি নিয়ন্ত্রিত মেমরি পরিবেশ প্রদান করে — যখন অ্যান্ড্রয়েড বুঝতে পারে যে আপনার অ্যাপ কিছু অবজেক্ট আর ব্যবহার করছে না, তখন গার্বেজ কালেক্টর অব্যবহৃত মেমরিকে হিপ-এ ফিরিয়ে দেয়। অ্যান্ড্রয়েড যেভাবে অব্যবহৃত মেমরি খুঁজে বের করে, তার ক্রমাগত উন্নতি হচ্ছে, কিন্তু সব অ্যান্ড্রয়েড সংস্করণে কোনো এক সময়ে সিস্টেমকে আপনার কোড কিছুক্ষণের জন্য থামাতে হয়। বেশিরভাগ সময়, এই বিরতিগুলো বোঝা যায় না। তবে, যদি আপনার অ্যাপ সিস্টেমের সংগ্রহের চেয়ে দ্রুত মেমরি বরাদ্দ করে, তাহলে কালেক্টর আপনার বরাদ্দকৃত মেমরি পূরণের জন্য পর্যাপ্ত মেমরি মুক্ত করতে যে সময় নেয়, ততক্ষণে আপনার অ্যাপটি বিলম্বিত হতে পারে। এই বিলম্বের কারণে আপনার অ্যাপ ফ্রেম স্কিপ করতে পারে এবং দৃশ্যমান ধীরগতি সৃষ্টি করতে পারে।

আপনার অ্যাপে ধীরগতি দেখা না গেলেও, যদি এটি মেমোরি লিক করে, তবে ব্যাকগ্রাউন্ডে থাকা অবস্থাতেও সেই মেমোরি ধরে রাখতে পারে। এই আচরণটি অপ্রয়োজনীয় গার্বেজ কালেকশন ইভেন্ট ঘটাতে বাধ্য করে সিস্টেমের বাকি মেমোরির পারফরম্যান্সকে ধীর করে দিতে পারে। অবশেষে, মেমোরি পুনরুদ্ধার করার জন্য সিস্টেম আপনার অ্যাপ প্রসেসটি বন্ধ করে দিতে বাধ্য হয়। এরপর যখন ব্যবহারকারী আপনার অ্যাপে ফিরে আসেন, তখন অ্যাপ প্রসেসটিকে সম্পূর্ণভাবে পুনরায় চালু করতে হয়।

যেসব প্রোগ্রামিং পদ্ধতি আপনার অ্যাপের মেমরি ব্যবহার কমাতে পারে, সে সম্পর্কে জানতে ‘আপনার অ্যাপের মেমরি পরিচালনা করুন ’ পড়ুন।

হিপ ডাম্পের সংক্ষিপ্ত বিবরণ

হিপ ডাম্প ক্যাপচার করতে, 'Analyze Memory Usage (Heap Dump)' টাস্কটি নির্বাচন করুন ( প্রোফাইলার ব্যবহার করুন: 'app' কে ডিবাগযোগ্য (সম্পূর্ণ ডেটা) হিসেবে চালান )। হিপ ডাম্প করার সময়, জাভা মেমরির পরিমাণ সাময়িকভাবে বেড়ে যেতে পারে। এটি স্বাভাবিক, কারণ হিপ ডাম্পটি আপনার অ্যাপের মতোই একই প্রসেসে ঘটে এবং ডেটা সংগ্রহের জন্য কিছু মেমরির প্রয়োজন হয়। হিপ ডাম্প ক্যাপচার করার পরে, আপনি নিম্নলিখিতটি দেখতে পাবেন:

অ্যান্ড্রয়েড স্টুডিও প্রোফাইলার-এর হিপ ডাম্প ভিউ।

ক্লাসগুলোর তালিকায় নিম্নলিখিত তথ্য দেখানো হচ্ছে:

  • অ্যালোকেশন : হিপে অ্যালোকেশনের সংখ্যা।
  • নেটিভ সাইজ : এই অবজেক্ট টাইপ দ্বারা ব্যবহৃত মোট নেটিভ মেমরির পরিমাণ (বাইটে)। আপনি এখানে জাভাতে বরাদ্দ করা কিছু অবজেক্টের জন্য মেমরি দেখতে পাবেন, কারণ অ্যান্ড্রয়েড কিছু ফ্রেমওয়ার্ক ক্লাসের জন্য, যেমন Bitmap , নেটিভ মেমরি ব্যবহার করে।

  • স্বল্প আকার : এই অবজেক্ট টাইপ দ্বারা ব্যবহৃত মোট জাভা মেমরির পরিমাণ (বাইটে)।

  • সংরক্ষিত আকার : এই ক্লাসের সমস্ত ইনস্ট্যান্সের কারণে সংরক্ষিত মোট মেমরির পরিমাণ (বাইটে)।

নির্দিষ্ট হিপগুলো ফিল্টার করতে হিপ মেনু ব্যবহার করুন:

  • অ্যাপ হিপ (ডিফল্ট) : প্রাথমিক হিপ, যেখানে আপনার অ্যাপ মেমরি বরাদ্দ করে।
  • ইমেজ হিপ : সিস্টেম বুট ইমেজ, যাতে এমন ক্লাসগুলো থাকে যা বুট হওয়ার সময় আগে থেকেই লোড করা হয়। এখানকার অ্যালোকেশনগুলো কখনো স্থানান্তরিত হয় না বা মুছে যায় না।
  • জাইগোট হিপ : অ্যান্ড্রয়েড সিস্টেমের সেই কপি-অন-রাইট হিপ, যেখান থেকে একটি অ্যাপ প্রসেস ফোর্ক করা হয়।

বরাদ্দগুলো কীভাবে বিন্যস্ত করবেন তা বেছে নিতে অ্যারেঞ্জমেন্ট ড্রপ-ডাউনটি ব্যবহার করুন:

  • শ্রেণী অনুসারে সাজান (ডিফল্ট) : শ্রেণীর নামের উপর ভিত্তি করে সমস্ত বরাদ্দকে গোষ্ঠীভুক্ত করে।
  • প্যাকেজ অনুযায়ী সাজান : প্যাকেজের নাম অনুসারে সমস্ত বরাদ্দকে শ্রেণিবদ্ধ করে।

ক্লাস ড্রপ-ডাউন ব্যবহার করে ক্লাসগুলোর বিভিন্ন গ্রুপে ফিল্টার করুন:

  • সকল ক্লাস (ডিফল্ট) : লাইব্রেরি এবং ডিপেন্ডেন্সি থেকে আসা ক্লাসগুলো সহ সমস্ত ক্লাস দেখায়।
  • অ্যাক্টিভিটি/ফ্র্যাগমেন্ট লিক দেখান : যে ক্লাসগুলো মেমোরি লিকের কারণ হচ্ছে, সেগুলো দেখায়।
  • প্রজেক্টের ক্লাসগুলো দেখান : শুধুমাত্র আপনার প্রজেক্টে সংজ্ঞায়িত ক্লাসগুলো দেখায়।

ইনস্ট্যান্স পেইনটি খোলার জন্য একটি ক্লাসের নামে ক্লিক করুন। তালিকাভুক্ত প্রতিটি ইনস্ট্যান্সে নিম্নলিখিত বিষয়গুলো অন্তর্ভুক্ত থাকে:

  • গভীরতা : যেকোনো GC রুট থেকে নির্বাচিত ইনস্ট্যান্স পর্যন্ত সর্বনিম্ন সংখ্যক হপ।
  • নেটিভ সাইজ : নেটিভ মেমরিতে এই ইনস্ট্যান্সটির আকার। এই কলামটি শুধুমাত্র অ্যান্ড্রয়েড ৭.০ এবং তার পরবর্তী সংস্করণগুলোতে দেখা যায়।
  • অগভীর আকার : জাভা মেমরিতে এই ইনস্ট্যান্সটির আকার।
  • সংরক্ষিত আকার : মেমোরির সেই আকার যা এই ইনস্ট্যান্সটি নিয়ন্ত্রণ করে ( ডমিনেটর ট্রি অনুসারে)।

একটি ইনস্ট্যান্সের ফিল্ড এবং রেফারেন্স সহ তার বিবরণ দেখতে ইনস্ট্যান্সটিতে ক্লিক করুন। সাধারণ ফিল্ড এবং রেফারেন্স টাইপগুলো হলো স্ট্রাকচার্ড টাইপ। অ্যারে এবং আদিম ডেটা প্রকার জাভাতে, সোর্স কোডে কোনো ফিল্ড বা রেফারেন্সের সাথে সম্পর্কিত ইনস্ট্যান্স বা লাইনে যেতে সেটির উপর রাইট-ক্লিক করুন।

  • ফিল্ডসমূহ : এই ইনস্ট্যান্সের সমস্ত ফিল্ড দেখায়।
  • রেফারেন্স : ইনস্ট্যান্স ট্যাবে হাইলাইট করা অবজেক্টটির প্রতিটি রেফারেন্স দেখায়।
হিপ ডাম্প টুল উইন্ডোতে থাকা ইনস্ট্যান্সেস , ফিল্ডস এবং রেফারেন্সেস ভিউ।

মেমরি লিক খুঁজুন

মেমরি লিকের সাথে সম্পর্কিত হতে পারে এমন ক্লাসগুলো দ্রুত ফিল্টার করতে, ক্লাস ড্রপ-ডাউনটি খুলুন এবং ‘Show activity/fragment leaks’ নির্বাচন করুন। অ্যান্ড্রয়েড স্টুডিও আপনার অ্যাপের Activity এবং Fragment ইনস্ট্যান্সগুলোর জন্য এমন ক্লাসগুলো দেখায়, যেগুলো তার মতে মেমরি লিকের ইঙ্গিত দেয়।

আরও ম্যানুয়ালি মেমরি লিক খুঁজতে, ক্লাস এবং ইনস্ট্যান্স লিস্ট ব্রাউজ করে বড় Retained Size যুক্ত অবজেক্টগুলো খুঁজুন। নিম্নলিখিত কারণগুলোর যেকোনো একটির ফলে সৃষ্ট মেমরি লিক অনুসন্ধান করুন:

  • Activity বা Context এর দীর্ঘস্থায়ী রেফারেন্স, যা হোস্ট করা Compose কম্পোজিশন গ্রাফ ফাঁস করে দিতে পারে (যেমন ComposeView এবং এর সাব-কম্পোজেবলগুলো)।
  • Jetpack Compose-এর State অবজেক্ট ( MutableState ), স্টেট হোল্ডার, বা Context ক্যাপচার করে এমন ল্যাম্বডা লিক হওয়া।
  • একটি DisposableEffect এর onDispose ব্লকে লিসেনার বা অবজারভারদের পরিষ্কার করতে ভুলে যাওয়া।
  • নন-স্ট্যাটিক ইনার ক্লাস, যেমন Runnable , যা একটি Activity ইনস্ট্যান্স ধারণ করতে পারে।
  • যেসব ক্যাশে প্রয়োজনের চেয়ে বেশি সময় ধরে অবজেক্ট ধরে রাখে।

যখন আপনি সম্ভাব্য মেমোরি লিক খুঁজে পাবেন, তখন ইনস্ট্যান্স ডিটেইলস- এর ফিল্ডস এবং রেফারেন্সেস ট্যাব ব্যবহার করে সরাসরি নির্দিষ্ট ইনস্ট্যান্স বা সোর্স কোড লাইনে চলে যান।

পরীক্ষার জন্য মেমরি লিক ট্রিগার করুন

মেমরি ব্যবহার বিশ্লেষণ করার জন্য, আপনার অ্যাপ কোডের উপর চাপ সৃষ্টি করা এবং মেমরি লিক ঘটানোর চেষ্টা করা উচিত। আপনার অ্যাপে মেমরি লিক ঘটানোর একটি উপায় হলো, হিপ পরীক্ষা করার আগে অ্যাপটিকে কিছুক্ষণ চলতে দেওয়া। লিকগুলো হিপের অ্যালোকেশনের শীর্ষ পর্যন্ত ধীরে ধীরে ছড়িয়ে পড়তে পারে। তবে, লিক যত ছোট হবে, তা দেখার জন্য অ্যাপটি তত বেশি সময় ধরে চালাতে হবে।

এছাড়াও আপনি নিম্নলিখিত উপায়গুলোর কোনো একটির মাধ্যমে মেমোরি লিক ঘটাতে পারেন:

  • বিভিন্ন অ্যাক্টিভিটি স্টেটে থাকা অবস্থায় ডিভাইসটিকে পোর্ট্রেট থেকে ল্যান্ডস্কেপে এবং আবার আগের অবস্থায় একাধিকবার ঘোরান। ডিভাইস ঘোরানোর ফলে প্রায়শই একটি Activity লিক হতে পারে (এবং ফলস্বরূপ এর হোস্ট করা কম্পোজ UI ট্রি এবং সংশ্লিষ্ট স্টেট ট্রিগুলোও লিক হয়ে যেতে পারে), যদি আপনার অ্যাপটি অ্যাসিঙ্ক্রোনাস অপারেশন বা স্টেট হোল্ডারের মধ্যে Activity বা Context কোনো রেফারেন্স ধরে রাখে।
  • বিভিন্ন অ্যাক্টিভিটি স্টেটে থাকাকালীন আপনার অ্যাপ এবং অন্য অ্যাপের মধ্যে সুইচ করুন। উদাহরণস্বরূপ, হোম স্ক্রিনে যান, তারপর আপনার অ্যাপে ফিরে আসুন।

হিপ ডাম্প রেকর্ডিং রপ্তানি এবং আমদানি করুন

আপনি প্রোফাইলারের 'পাস্ট রেকর্ডিংস' ট্যাব থেকে একটি হিপ ডাম্প ফাইল এক্সপোর্ট এবং ইম্পোর্ট করতে পারেন। অ্যান্ড্রয়েড স্টুডিও রেকর্ডিংটি একটি .hprof ফাইল হিসেবে সংরক্ষণ করে।

বিকল্পভাবে, jhat-এর মতো অন্য কোনো .hprof ফাইল অ্যানালাইজার ব্যবহার করতে হলে, আপনাকে .hprof ফাইলটিকে অ্যান্ড্রয়েড ফরম্যাট থেকে Java SE .hprof ফাইল ফরম্যাটে রূপান্তর করতে হবে। ফাইল ফরম্যাটটি রূপান্তর করার জন্য, {android_sdk}/platform-tools/ ডিরেক্টরিতে দেওয়া hprof-conv টুলটি ব্যবহার করুন। hprof-conv কমান্ডটি দুটি আর্গুমেন্ট সহ চালান: আসল .hprof ফাইলের নাম এবং রূপান্তরিত .hprof ফাইলটি লেখার স্থান, যেখানে নতুন .hprof ফাইলের নামটিও অন্তর্ভুক্ত থাকবে। উদাহরণস্বরূপ:

hprof-conv heap-original.hprof heap-converted.hprof

অতিরিক্ত সম্পদ