মোবাইল ডেভেলপমেন্টে Runtime: এটি কী, runtime সিস্টেম এবং কীভাবে কাজ করে

লেখক: IT Sectr প্রকাশিত: 2026-05-17 পড়ার সময়: 9 মিনিট

Runtime হল একটি সফ্টওয়্যার স্তর যা মোবাইল অ্যাপ্লিকেশন কোডের নির্বাহ পরিচালনা করে: মেমরি বরাদ্দ করে, ব্যতিক্রম হ্যান্ডল করে, গার্বেজ কালেকশন চালায় এবং মেথড কল ডিসপ্যাচ করে। runtime ছাড়া কোনো অ্যাপ্লিকেশন নির্বাহ করা যায় না — এটি কম্পাইল করা কোড এবং অপারেটিং সিস্টেমের মধ্যবর্তী স্তর। Android Developer Documentation, 2025 অনুসারে, রানটাইম পরিবেশ হল প্ল্যাটফর্মের একটি মূল উপাদান যা কর্মক্ষমতা এবং সামঞ্জস্য নির্ধারণ করে।

মূল পয়েন্ট

  • Runtime হল সফ্টওয়্যার পরিবেশ যা মোবাইল অ্যাপ্লিকেশনের বাইটকোড বা মেশিন কোড নির্বাহ করে।
  • ART (Android Runtime) AOT কম্পাইলেশন ব্যবহার করে এবং Android 5.0 থেকে Dalvik-কে প্রতিস্থাপন করেছে।
  • Objective-C Runtime iOS-এ ডায়নামিক মেথড ডিসপ্যাচ এবং মেসেজ পাসিং প্রদান করে।
  • JIT কম্পাইলেশন অ্যাপ্লিকেশন নির্বাহের সময় সরাসরি বাইটকোডকে মেশিন কোডে কম্পাইল করে।
  • ARM64 Runtime হল হার্ডওয়্যার স্তর যেখানে 64-বিট ARM প্রসেসরের জন্য অপ্টিমাইজ করা কোড নির্বাহিত হয়।

মোবাইল ডেভেলপমেন্টে Runtime কী?

Runtime হল পরিকাঠামো যা প্রোগ্রাম চালু হওয়ার পরে তার নির্বাহ নিশ্চিত করে। মোবাইল ডেভেলপমেন্টের প্রসঙ্গে, runtime-এর মধ্যে ক্লাস লোডার, মেমরি বরাদ্দকারী, গার্বেজ কালেক্টর, মেথড ডিসপ্যাচার এবং ব্যতিক্রম হ্যান্ডলার অন্তর্ভুক্ত। এই মধ্যবর্তী স্তর ছাড়া, অপারেটিং সিস্টেম Dalvik বাইটকোড বা Objective-C বার্তা নির্বাহ করতে পারে না।

মোবাইল প্ল্যাটফর্মগুলি বিভিন্ন runtime বাস্তবায়ন ব্যবহার করে। Android হাইব্রিড AOT/JIT কম্পাইলেশন সহ ART (Android Runtime) ব্যবহার করে। iOS Objective-C Runtime ব্যবহার করে — একটি ডায়নামিক সিস্টেম যা মেসেজ পাসিং এবং SEL আইডেন্টিফায়ারের উপর ভিত্তি করে। উভয় পদ্ধতি একই সমস্যা সমাধান করে: একটি নির্দিষ্ট ডিভাইসে সর্বাধিক কর্মক্ষমতা সহ ডেভেলপারের কোড নির্বাহ করা।

Google I/O 2024 অনুসারে, Android Runtime সারা বিশ্বের ডিভাইসগুলিতে প্রতিদিন 10 বিলিয়নেরও বেশি মেথড প্রক্রিয়া করে। Runtime কর্মক্ষমতা সরাসরি অ্যাপ্লিকেশন লঞ্চ গতি, অ্যানিমেশনের মসৃণতা এবং ব্যাটারি খরচকে প্রভাবিত করে। প্রতিটি মেথড কল, প্রতিটি মেমরি বরাদ্দ এবং প্রতিটি গার্বেজ কালেকশন চক্র runtime স্তরের মধ্য দিয়ে যায়।

Runtime সিস্টেম: এটি কী কী উপাদান নিয়ে গঠিত

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

ক্লাস লোডার এবং যাচাইকরণ

যখন একজন ব্যবহারকারী একটি অ্যাপ্লিকেশন চালু করেন, ClassLoader DEX ফাইল (Android) বা Mach-O বাইনারি (iOS) RAM-এ লোড করে। Android-এ, এই ধাপে বাইটকোড যাচাইকরণ অন্তর্ভুক্ত: runtime পরীক্ষা করে যে কোডে কোনো অনিরাপদ নির্দেশনা নেই, অ্যারে সীমার বাইরে যায় না এবং টাইপ মেনে চলে। যাচাইকরণ একটি গুরুত্বপূর্ণ নিরাপত্তা পদক্ষেপ যা দূষিত কোড নির্বাহ প্রতিরোধ করে।

মেমরি ম্যানেজার এবং গার্বেজ কালেক্টর

মেমরি ম্যানেজার অবজেক্টের জন্য মেমরি বরাদ্দ এবং মুক্ত করে। Android ART-তে, জেনারেশনাল কালেকশন সহ একটি কনকারেন্ট গার্বেজ কালেক্টর ব্যবহার করা হয়: তরুণ অবজেক্ট বেশি বার পরীক্ষা করা হয়, পুরানো কম বার। Objective-C Runtime অটোমেটিক রেফারেন্স কাউন্টিং (ARC) ব্যবহার করে, যেখানে কম্পাইলার স্বয়ংক্রিয়ভাবে retain/release কল সন্নিবেশ করে।

মেথড ডিসপ্যাচার এবং ভার্চুয়াল টেবিল

মেথড ডিসপ্যাচার নির্ধারণ করে যে মেথডের কোন বাস্তবায়ন কল করা হবে। স্ট্যাটিক ভাষায় (Kotlin, Swift), ডিসপ্যাচ vtable — ভার্চুয়াল মেথড টেবিলের মাধ্যমে সম্পাদিত হয়। ডায়নামিক ভাষায় (Objective-C), বার্তা objc_msgSend-এর মধ্য দিয়ে যায়, যা ক্লাস এবং তার সুপারক্লাসে বাস্তবায়ন খুঁজে বের করে। ফলাফল বারবার কল দ্রুত করার জন্য method cache-এ ক্যাশ করা হয়।

Android-এ ART কীভাবে কাজ করে

Android Runtime (ART) একটি ভার্চুয়াল মেশিন যা Android অ্যাপ্লিকেশনের DEX বাইটকোড নির্বাহ করে। ART Android 5.0 Lollipop-এ Dalvik-কে প্রতিস্থাপন করেছে, AOT কম্পাইলেশন চালু করেছে: অ্যাপ্লিকেশন ইনস্টলেশনের সময় একবার মেশিন কোডে কম্পাইল হয়। এটি প্রতিটি লঞ্চে JIT কম্পাইলেশনের ওভারহেড দূর করেছে।

Android 7.0 Nougat থেকে শুরু করে, ART একটি হাইব্রিড পদ্ধতি ব্যবহার করে। ইনস্টলেশনের সময়, JIT কম্পাইলেশন শুধুমাত্র ঘন ঘন ব্যবহৃত মেথডের (hot methods) জন্য সম্পাদিত হয়, বাকি কোড ব্যাখ্যা করা হয়। একটি ব্যাকগ্রাউন্ড প্রক্রিয়া (profile-guided optimization) বিশ্লেষণ করে কোন মেথড সবচেয়ে বেশি কল করা হয় এবং ডিভাইসের নিষ্ক্রিয় সময়ে সেগুলিকে AOT কম্পাইল করে। এটি উচ্চ কর্মক্ষমতা নিশ্চিত করার পাশাপাশি ইনস্টলেশন সময় হ্রাস করে।

ART-তে একটি AOT কম্পাইলার (dex2oat) অন্তর্ভুক্ত রয়েছে যা DEX ফাইলগুলিকে ARM64 মেশিন কোড সহ ELF বাইনারিতে রূপান্তর করে। কম্পাইলেশন তিনটি অপ্টিমাইজেশন স্তরের সাথে সম্পাদিত হয়: quicken (দ্রুত), optimize (মধ্যম) এবং everything (সম্পূর্ণ)। ডিফল্টরূপে, Android optimize ব্যবহার করে, যা কম্পাইলেশন গতি এবং কোড কর্মক্ষমতার মধ্যে ভারসাম্য রাখে।

kotlin
class RuntimeExample {
    fun measureExecutionTime() {
        val start = System.nanoTime()
        // ART দ্বারা কম্পাইল করা মেথড কল
        processData()
        val end = System.nanoTime()
        println("নির্বাহ সময়: ${end - start} ন্যানোসেকেন্ড")
    }
}

উপরের উদাহরণে, System.nanoTime() একটি নেটিভ মেথড যার কল ART runtime-এর মাধ্যমে Linux কার্নেলে ডিসপ্যাচ হয়। ART Kotlin বাইটকোডকে ARM64 নির্দেশে রূপান্তর করে যা ডিভাইসের প্রসেসর দ্বারা নির্বাহিত হয়। এই প্রক্রিয়াটি ডেভেলপারের কাছে স্বচ্ছ, কিন্তু এর অপ্টিমাইজেশন Android Platform টিমের একটি মূল কাজ।

Profile-Guided Optimization (PGO)

Profile-guided optimization একটি ART প্রক্রিয়া যা মেথড ব্যবহারের প্রোফাইল সংগ্রহ করে। ফাইল profiles/.primary.prof-এ hot মেথডের তালিকা থাকে যা AOT কম্পাইল হয়। Android Performance Team-এর মতে, PGO প্রোফাইল জমা হওয়ার পরে কয়েক দিন ব্যবহারের পর অ্যাপ্লিকেশন লঞ্চ 15–30% দ্রুত করে।

ডেভেলপার তার Gradle প্রকল্পে baseline profiles সক্ষম করতে পারেন। এগুলি ম্যানুয়াল অ্যানোটেশন যা ART-কে জানায় যে ইনস্টলেশনের পরপরই কোন মেথড AOT কম্পাইল করতে হবে। Baseline profiles ব্যাকগ্রাউন্ড প্রোফাইলিংয়ের অপেক্ষা না করেই প্রথম লঞ্চ 40% কমিয়ে দেয়।

iOS-এ Objective-C Runtime কীভাবে কাজ করে

Objective-C Runtime একটি ডায়নামিক লাইব্রেরি যা iOS এবং macOS-এ Objective-C কোডের নির্বাহ প্রদান করে। এর মূল হল objc_msgSend ফাংশন, যা মেসেজ পাসিং বাস্তবায়ন করে: সরাসরি মেথড কলের পরিবর্তে, অবজেক্ট একটি সিলেক্টর সহ একটি বার্তা পাঠায়, এবং runtime নির্ধারণ করে কোন বাস্তবায়ন নির্বাহ করা উচিত।

প্রতিটি Objective-C অবজেক্টে তার ক্লাসের জন্য একটি isa পয়েন্টার থাকে, এবং ক্লাসে একটি dispatch table থাকে যা সিলেক্টর (SEL) থেকে বাস্তবায়ন (IMP) ম্যাপ করে। যখন একটি মেথড কল করা হয়, objc_msgSend শৃঙ্খল: ক্লাস → সুপারক্লাস → NSObject ট্রাভার্স করে, যতক্ষণ না IMP খুঁজে পায়। যদি কোনো বাস্তবায়ন না পাওয়া যায়, runtime forwarding mechanism কল করে, যা বার্তাটি আটকাতে বা একটি ব্যতিক্রম তৈরি করতে পারে।

Objective-C Runtime method swizzling-ও সমর্থন করে — রানটাইমে বিদ্যমান সিলেক্টরের IMP প্রতিস্থাপন করা। এটি একটি শক্তিশালী প্রক্রিয়া যা AOP লাইব্রেরি এবং মনিটরিং টুলে ব্যবহৃত হয়, কিন্তু পুরো অ্যাপ্লিকেশনে এর প্রভাবের কারণে সতর্কতা প্রয়োজন।

objective-c
@interface RuntimeDemo : NSObject
- (void)printClassInfo;
@end

@implementation RuntimeDemo
- (void)printClassInfo {
    // objc_getClass — runtime ফাংশন
    Class cls = objc_getClass("RuntimeDemo");
    unsigned int count;
    Method *methods = class_copyMethodList(cls, &count);
    NSLog("মেথডের সংখ্যা: %d", count);
}
@end

কোডটি Objective-C Runtime API-তে সরাসরি অ্যাক্সেস প্রদর্শন করে: objc_getClass নাম দ্বারা ক্লাস অবজেক্ট পায়, class_copyMethodList সব মেথডের তালিকা বের করে। এটি কর্মে রিফ্লেকশন — রানটাইমে ক্লাস মেটাডেটা অ্যাক্সেস। এই পদ্ধতিটি XCTest-এ ডায়নামিক টেস্ট রেজিস্ট্রেশনের জন্য ব্যবহৃত হয়।

isa পয়েন্টার এবং tagged pointers

isa পয়েন্টার প্রতিটি অবজেক্টের প্রথম 8 বাইটে সংরক্ষিত অবজেক্টের ক্লাসের একটি পয়েন্টার। iOS 12 থেকে শুরু করে, Apple অপ্টিমাইজেশনের জন্য isa-swizzling চালু করেছে: isa-র নিম্ন বিটগুলি অবজেক্টের অবস্থা সম্পর্কে অতিরিক্ত তথ্য এনকোড করে। Tagged pointers আরেকটি অপ্টিমাইজেশন যেখানে 60 বিট পর্যন্ত মান (NSNumber, NSDate) হিপে অবজেক্ট বরাদ্দ না করে সরাসরি পয়েন্টারে সংরক্ষিত হয়। এটি মেমরি ম্যানেজার লোড 30% কমায়।

JIT বনাম AOT কম্পাইলেশন: পদ্ধতির তুলনা

JIT (Just-In-Time) এবং AOT (Ahead-Of-Time) বাইটকোডকে মেশিন কোডে কম্পাইল করার দুটি পদ্ধতি। JIT অ্যাপ্লিকেশন নির্বাহের সময় কোড কম্পাইল করে, হট স্পট বিশ্লেষণ করে এবং সেগুলিকে তাৎক্ষণিকভাবে অপ্টিমাইজ করে। AOT সমস্ত কোড আগে থেকেই কম্পাইল করে — অ্যাপ্লিকেশন ইনস্টলেশনের সময় বা ডেভেলপারের পক্ষ থেকে।

বৈশিষ্ট্যJITAOT
কম্পাইলেশন সময়নির্বাহের সময়ইনস্টলেশন/বিল্ডের সময়
APK/IPA আকারছোট (শুধু বাইটকোড)বড় (মেশিন কোড)
লঞ্চ গতিকম (কম্পাইলেশন প্রয়োজন)বেশি (কোড প্রস্তুত)
ডিভাইস-নির্দিষ্ট অপ্টিমাইজেশনহ্যাঁ (অভিযোজিত)সীমিত (সাধারণ)
RAM খরচবেশি (মেমরিতে কম্পাইলার)কম

ART হাইব্রিড পদ্ধতি (Android 7+) সর্বোত্তম বলে বিবেচিত: অ্যাপ্লিকেশন খুব কমই কল করা মেথডের জন্য ইন্টারপ্রেটার, hot মেথডের জন্য JIT এবং profile-guided optimization থেকে মেথডের জন্য AOT ব্যবহার করে। iOS, বিপরীতে, LLVM-এর মাধ্যমে কঠোর AOT ব্যবহার করে: Swift এবং Objective-C Xcode-এ বিল্ড ধাপের সময় মেশিন কোডে কম্পাইল হয়।

Apple Developer Documentation, 2024 অনুসারে, Swift runtime অ্যাপ্লিকেশন আকারে প্রায় 15 MB যোগ করে। Flutter তার নিজস্ব Dart VM ব্যবহার করে, যেখানে JIT কম্পাইলেশন hot reload-এর জন্য ডিবাগ মোডে কাজ করে, এবং AOT সর্বাধিক কর্মক্ষমতার জন্য রিলিজ মোডে কাজ করে। React Native Hermes ব্যবহার করে — AOT কম্পাইলেশন সহ একটি JavaScript ইঞ্জিন যা লঞ্চ সময় 50% কমায়।

ARM64 Runtime এবং মেশিন কোড

ARM64 Runtime হল স্তর যেখানে মেশিন কোড ডিভাইসের প্রসেসরের সাথে যোগাযোগ করে। অধিকাংশ আধুনিক মোবাইল ডিভাইস ARM64 (aarch64) প্রসেসরে চলে। Runtime বাইটকোড বা নেটিভ কলকে ARM64 নির্দেশে অনুবাদ করে যা CPU নির্বাহ করে।

Runtime দ্বারা ব্যবহৃত মূল ARM64 রেজিস্টার: x0–x7 (ফাংশন প্যারামিটার), x8 (পরোক্ষ ফলাফল), x30 (রিটার্ন ঠিকানা), sp (স্ট্যাক পয়েন্টার), fp (ফ্রেম পয়েন্টার)। ART ARM64 Procedure Call Standard অনুসরণকারী কোড তৈরি করে: সমস্ত মেথড কল প্রসেসর আর্কিটেকচার দ্বারা সংজ্ঞায়িত প্রোটোকলের মধ্য দিয়ে যায়।

ARM64 ABI বোঝা কর্মক্ষমতা অপ্টিমাইজেশনের জন্য গুরুত্বপূর্ণ: ইনলাইন ক্যাশিং, ব্রাঞ্চ প্রেডিকশন এবং মেমরিতে কোড সারিবদ্ধকরণ সরাসরি runtime গতিকে প্রভাবিত করে। প্রোফাইলিং টুল (Android Studio Profiler, Instruments) দেখায় কোন কোড বিভাগ runtime-এ সবচেয়ে বেশি সময় ব্যয় করে — এগুলিকে অপ্টিমাইজ করা সবচেয়ে বড় উন্নতি দেয়।

cpp
// ART দ্বারা উৎপন্ন ARM64 অ্যাসেম্বলির উদাহরণ
// দুই প্যারামিটার সহ মেথড কল

mov    x0, x23            // self (this)
mov    x1, x24            // param1
mov    x2, x25            // param2
bl     methodEntryPoint   // runtime-এর মাধ্যমে কল
str    x0, [sp, #8]      // ফলাফল সংরক্ষণ

এই উদাহরণে, ARM64 নির্দেশ mov রেজিস্টার x0–x2-এ আর্গুমেন্ট পাস করে, bl মেথড এন্ট্রি পয়েন্ট কল করে, এবং str রিটার্ন মান সংরক্ষণ করে। Runtime প্রতিটি মেথড কলের জন্য এই ধরনের নির্দেশ তৈরি করে, devirtualization এবং inlining-এর মাধ্যমে ক্রম অপ্টিমাইজ করে।

কর্মক্ষমতার উপর Runtime-এর প্রভাব

Runtime ওভারহেড ডায়নামিক ডিসপ্যাচের অনিবার্য মূল্য। Runtime-এর মাধ্যমে প্রতিটি মেথড কলের জন্য প্রয়োজন: dispatch table-এ বাস্তবায়ন খোঁজা, টাইপ পরীক্ষা, IMP কল করা এবং ফলাফল ফিরিয়ে দেওয়া। পরিমাপ দেখায় যে runtime Objective-C-তে প্রতি কল 10–50 ন্যানোসেকেন্ড এবং ART-তে 5–20 ন্যানোসেকেন্ড যোগ করে।

ওভারহেড কমানোর জন্য, ডেভেলপাররা monomorphic inlining (ART) এবং method caching (Objective-C) ব্যবহার করে। Kotlin/Native এবং Swift সরাসরি ARM64-এ কম্পাইল হয়, runtime স্তর সম্পূর্ণরূপে দূর করে, কিন্তু ডায়নামিক ক্ষমতা — রিফ্লেকশন, swizzling, ডায়নামিক ক্লাস লোডিং হারায়।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

Runtime SDK থেকে কীভাবে আলাদা?

SDK (Software Development Kit) হল অ্যাপ্লিকেশন ডেভেলপমেন্টের জন্য টুলের একটি সেট (কম্পাইলার, লাইব্রেরি, ইউটিলিটি)। Runtime হল পরিবেশ যেখানে ইতিমধ্যে উন্নত অ্যাপ্লিকেশন ডিভাইসে চলে। ডেভেলপারের SDK প্রয়োজন, ব্যবহারকারীর runtime প্রয়োজন।

মোবাইল অ্যাপ্লিকেশনে কি Runtime প্রতিস্থাপন করা যায়?

না — runtime অপারেটিং সিস্টেমের অংশ এবং ব্যবহারকারী দ্বারা প্রতিস্থাপন করা যায় না। ART Android Framework-এ নির্মিত, Objective-C Runtime iOS-এ। ডেভেলপার ভাষা বেছে নিতে পারেন (Kotlin/Native runtime ছাড়া) বা Flutter-এ Dart VM-এর মতো ভার্চুয়াল মেশিন ব্যবহার করতে পারেন।

Runtime কি ব্যাটারি খরচকে প্রভাবিত করে?

হ্যাঁ, runtime শক্তি খরচকে প্রভাবিত করে। ART এবং Swift runtime-এ গার্বেজ কালেকশন CPU ব্যবহার করে, যা ব্যাটারি খরচ বাড়ায়। iOS-এ concurrent GC এবং tagged pointers-এর মতো অপ্টিমাইজেশন ব্যাটারিতে runtime-এর প্রভাব 20–30% কমায়।

Runtime error কী এবং কীভাবে এটি ধরা যায়?

Runtime error হল একটি ত্রুটি যা নির্বাহের সময় ঘটে: null pointer exception, index out of bounds, শূন্য দ্বারা ভাগ। কম্পাইল-টাইম ত্রুটির বিপরীতে, এগুলি বিল্ডের সময় সনাক্ত হয় না। এগুলি try-catch ব্লক বা ক্র্যাশ রিপোর্টিং (Firebase Crashlytics, Sentry) এর মাধ্যমে ধরা হয়।

Swift runtime কীভাবে Objective-C Runtime থেকে আলাদা?

Swift runtime Objective-C-এর চেয়ে হালকা: এটি ডিফল্টরূপে ডায়নামিক ডিসপ্যাচ সমর্থন করে না, হিপ বরাদ্দ ছাড়া value types (struct) ব্যবহার করে এবং এতে message forwarding নেই। Swift মেথড @objc dynamic চিহ্নিত না থাকলে সরাসরি vtable-এর মাধ্যমে কল হয়। এটি বেঞ্চমার্কে 5x পর্যন্ত গতি উন্নতি দেয়।

সারাংশ

  • Runtime একটি নির্বাহ পরিবেশ যা মেমরি, মেথড এবং কোড নিরাপত্তা পরিচালনা করে।
  • ART (Android) সর্বোত্তম কর্মক্ষমতার জন্য profile-guided optimization সহ হাইব্রিড JIT/AOT পদ্ধতি ব্যবহার করে।
  • Objective-C Runtime objc_msgSend এবং dispatch table-এর মাধ্যমে মেসেজ পাসিং-এর উপর নির্মিত।
  • JIT কোড তাৎক্ষণিকভাবে কম্পাইল করে এবং ডিভাইসের সাথে খাপ খায়, AOT দ্রুত শুরুর জন্য আগে থেকেই কম্পাইল করে।
  • ARM64 Runtime হল হার্ডওয়্যার স্তর যা আধুনিক প্রসেসরে মেশিন কোড নির্বাহ করে।
  • Runtime ওভারহেড প্রতি মেথড কল 5–50 ন্যানোসেকেন্ড এবং ইনলাইনিং এবং ক্যাশিং-এর মাধ্যমে কমানো হয়।
  • কর্মক্ষমতা অপ্টিমাইজেশন, ডিবাগিং এবং অ্যাপ্লিকেশন আর্কিটেকচার বেছে নেওয়ার জন্য runtime বোঝা প্রয়োজন।

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন