ওহে!

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

একটি সত্যিকারের বৃহৎ প্রোগ্রামে, দশ হাজার এবং কয়েক হাজার বস্তু তৈরি করা হয়, এবং তাদের প্রত্যেকের নিজস্ব মেমরির জন্য বরাদ্দ করা হয়। কিন্তু এই সব বস্তুর অস্তিত্ব কতদিন মনে হয়? তারা কি আমাদের প্রোগ্রাম চলাকালীন পুরো সময় "লাইভ" করে? অবশ্যই না. এমনকি জাভা অবজেক্টের সমস্ত সুবিধার সাথেও, তারা অমর নয় :) অবজেক্টের নিজস্ব জীবনচক্র আছে। আজ আমরা কোড লেখা থেকে একটু বিরতি নেব এবং এই প্রক্রিয়াটি দেখব :) তাছাড়া, একটি প্রোগ্রাম কীভাবে কাজ করে এবং কীভাবে সংস্থানগুলি পরিচালনা করা হয় তা আপনার বোঝার জন্য এটি খুবই গুরুত্বপূর্ণ। তাহলে, কখন বস্তুর জীবন শুরু হয়? একজন ব্যক্তির মতো—তার জন্ম থেকেই, অর্থাৎ সৃষ্টি।


Cat cat = new Cat(); // Here the lifecycle of our Cat object begins!

প্রথমত, জাভা ভার্চুয়াল মেশিন বস্তুটি তৈরি করতে প্রয়োজনীয় পরিমাণ মেমরি বরাদ্দ করে। তারপর এটি সেই স্মৃতির একটি রেফারেন্স তৈরি করে। আমাদের ক্ষেত্রে, সেই রেফারেন্সটিকে বলা হয় cat, তাই আমরা এটির ট্র্যাক রাখতে পারি। তারপর এর সমস্ত ভেরিয়েবল শুরু করা হয়, কনস্ট্রাক্টর বলা হয়, এবং —তা-দা! - আমাদের সদ্য-নির্মিত বস্তু তার নিজের জীবন যাপন করছে :)

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


public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}

ল্যাম্বরগিনি ডায়াবলো গাড়ির বস্তুটি পদ্ধতির দ্বিতীয় লাইনে জীবিত হওয়া বন্ধ করে দেয় main()। এটিতে শুধুমাত্র একটি রেফারেন্স ছিল, এবং তারপর সেই রেফারেন্সটি এর সমান সেট করা হয়েছিল null। যেহেতু ল্যাম্বরগিনি ডায়াবলোর কোন রেফারেন্স অবশিষ্ট নেই, তাই বরাদ্দকৃত স্মৃতি "আবর্জনা" হয়ে যায়। এটি হওয়ার জন্য একটি রেফারেন্স নাল সেট করতে হবে না:


public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}

এখানে আমরা একটি দ্বিতীয় অবজেক্ট তৈরি করেছি এবং তারপর এই নতুন অবজেক্টটিকে রেফারেন্সে বরাদ্দ করেছি lamborghini। এখন Lamborghini Gallardoঅবজেক্টের দুটি রেফারেন্স আছে, কিন্তু Lamborghini Diabloবস্তুর কোনটি নেই। তার মানে Diabloবস্তুটি এখন আবর্জনা। যখন জাভা এর অন্তর্নির্মিত প্রক্রিয়া যাকে আবর্জনা সংগ্রহকারী (GC) বলা হয় তা কার্যকর হয়।

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

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

যখন আবর্জনা সংগ্রাহক একটি বস্তুর কাছে পৌঁছায়, বস্তুটিকে ধ্বংস করার ঠিক আগে, এটি একটি বিশেষ পদ্ধতিকে কল করে —— finalize()বস্তুটির উপর। এই পদ্ধতি অবজেক্ট দ্বারা ব্যবহৃত অন্যান্য সম্পদ প্রকাশ করতে পারে। পদ্ধতিটি finalize()ক্লাসের অংশ Objectequals()এর মানে হল যে , hashCode()এবং পদ্ধতিগুলি ছাড়াও toString()যেগুলি আপনি আগে দেখেছিলেন, প্রতিটি বস্তুর এই পদ্ধতি রয়েছে। এটি অন্যান্য পদ্ধতির থেকে আলাদা যে এটি - আমি এটি কীভাবে রাখব - খুব কৌতুকপূর্ণ।

বিশেষ করে, এটি একটি বস্তুর ধ্বংসের আগে সবসময় বলা হয় না। প্রোগ্রামিং একটি সুনির্দিষ্ট প্রচেষ্টা। প্রোগ্রামার কম্পিউটারকে কিছু করতে বলে, আর কম্পিউটার তা করে। আমি মনে করি আপনি ইতিমধ্যে এই আচরণে অভ্যস্ত, তাই প্রথমে এই নিম্নলিখিত ধারণাটি গ্রহণ করা আপনার পক্ষে কঠিন হতে পারে: "বস্তু ধ্বংসের আগে, finalize()ক্লাসের পদ্ধতিটি Objectবলা হয়। বা হয়তো এটি বলা হয় না। এটি সব নির্ভর করে তোমার ভাগ্য!"

তবুও, এটা সত্য. finalize()জাভা মেশিন নিজেই নির্ধারণ করে যে পদ্ধতিটিকে কেস-বাই-কেস ভিত্তিতে কল করা হবে কিনা । উদাহরণস্বরূপ, একটি পরীক্ষা হিসাবে নিম্নলিখিত কোড চালানোর চেষ্টা করা যাক:


public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {
       for (int i = 0 ; i < 1000000; i++) {
           Cat cat = new Cat();
           cat = null; // This is when the first object becomes available to the garbage collector
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Cat object destroyed!");
   }
}

আমরা একটি Catঅবজেক্ট তৈরি করি এবং তারপর কোডের পরবর্তী লাইনে আমরা তার একমাত্র রেফারেন্সটি null এর সমান সেট করি। এবং আমরা এটি এক মিলিয়ন বার করি। আমরা স্পষ্টভাবে finalize()পদ্ধতিটিকে ওভাররড করেছি যাতে এটি কনসোলে একটি স্ট্রিং এক মিলিয়ন বার প্রিন্ট করে (প্রতিবার এটি একটি Catবস্তুকে ধ্বংস করে)। কিন্তু না! সুনির্দিষ্টভাবে বলতে গেলে, এটি আমার কম্পিউটারে মাত্র 37,346 বার চলে! অর্থাৎ, 27 বারের মধ্যে একবার আমার মেশিনে ইনস্টল করা জাভা মেশিনটি finalize()পদ্ধতিটিকে কল করার সিদ্ধান্ত নিয়েছে।

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

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

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

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

আপনার এটি মুখস্থ করার দরকার নেই। আপনি শুধু এটি কিভাবে কাজ করে পিছনে নীতি বুঝতে হবে.