Global Exception Handler — একটি কেন্দ্রীভূত ব্যবস্থা যা অপ্রক্রিয়াজাত ব্যতিক্রমগুলি ধরে এবং মোবাইল অ্যাপের ক্র্যাশ প্রতিরোধ করে। Apple Developer, 2024 অনুসারে, সঠিক ব্যতিক্রম হ্যান্ডলিং ক্র্যাশের সংখ্যা 40–60% কমায় এবং ব্যবহারকারীর অভিজ্ঞতা উন্নত করে। এই ধরনের হ্যান্ডলার ছাড়া, ব্যাকগ্রাউন্ড থ্রেডে যেকোনো অপ্রক্রিয়াজাত ব্যতিক্রম তাৎক্ষণিকভাবে অ্যাপ বন্ধ করে দেয়।
মূল পয়েন্ট
Global Exception Handler — একটি কেন্দ্রীভূত ব্যবস্থা যা সেই ব্যতিক্রমগুলি ধরে যা অ্যাপের পৃথক ফাংশন বা মডিউল স্তরে প্রক্রিয়া করা হয়নি। মোবাইল ডেভেলপমেন্টের প্রসঙ্গে, এই ধরনের হ্যান্ডলার প্রক্রিয়ার অস্বাভাবিক সমাপ্তির আগে শেষ প্রতিরক্ষা লাইন হিসাবে কাজ করে।
iOS এবং Android বৈশ্বিক হ্যান্ডলার সেট করার জন্য অন্তর্নির্মিত API প্রদান করে। Apple Objective-C পরিবেশের জন্য NSSetUncaughtExceptionHandler ব্যবহার করে, যখন Google Java/Kotlin-এ Thread.setDefaultUncaughtExceptionHandler প্রদান করে। উভয় ব্যবস্থা অ্যাপের সকল থ্রেডে try-catch কাঠামো দ্বারা ধরা না হওয়া ব্যতিক্রমগুলি ধরে।
Crashlytics (Google, 2024) অনুসারে, প্রায় 25% ক্র্যাশ ব্যাকগ্রাউন্ড থ্রেডে অপ্রক্রিয়াজাত ব্যতিক্রমের কারণে ঘটে — একটি ক্ষেত্র যেখানে Global Exception Handler বিশেষভাবে গুরুত্বপূর্ণ। ডেভেলপাররা প্রায়ই UI থ্রেডে মনোযোগ দেয়, অ্যাসিঙ্ক্রোনাস অপারেশনগুলি ভুলে যায়।
বৈশ্বিক হ্যান্ডলার ব্যবহার স্থানীয় ত্রুটি হ্যান্ডলিং প্রতিস্থাপন করে না বরং এটিকে পরিপূরক করে। প্রধান কাজ হল ব্যতিক্রমের মুহূর্তে অ্যাপের অবস্থা সম্পর্কে সর্বোচ্চ তথ্য সংরক্ষণ করা এবং সঠিকভাবে সমাপ্ত করা।
কাজের প্রক্রিয়া Global Exception Handler অপারেটিং সিস্টেম সিগন্যাল বা রানটাইম ব্যতিক্রম আটকানোর উপর ভিত্তি করে। যখন কোড একটি ব্যতিক্রম ছোঁড়ে যা কোনো try-catch ব্লক দ্বারা ধরা পড়ে না, তখন নিয়ন্ত্রণ পূর্ব-নিবন্ধিত হ্যান্ডলারে স্থানান্তরিত হয়।
iOS-এ, হ্যান্ডলার NSSetUncaughtExceptionHandler এর মাধ্যমে নিবন্ধিত হয় এবং সম্পূর্ণ স্ট্যাক ট্রেস সহ একটি NSException অবজেক্ট গ্রহণ করে। Android-এ, Thread.setDefaultUncaughtExceptionHandler ব্যবহার করা হয়, যা Thread এবং Throwable গ্রহণ করে — যা ব্যতিক্রমের ধরন, বার্তা এবং কল স্ট্যাকে অ্যাক্সেস দেয়।
ক্র্যাশ ডেটা পাওয়ার পর, হ্যান্ডলার তিনটি বাধ্যতামূলক কাজ করে: স্থানীয় স্টোরেজে লগ লেখা, Crashlytics বা Sentry-তে রিপোর্ট পাঠানো, এবং অ্যাপ সঠিকভাবে সমাপ্ত করা। Apple WWDC 2023 অনুসারে, হ্যান্ডলারের নির্বাহ সময় 5 সেকেন্ড এ সীমাবদ্ধ — তারপর সিস্টেম জোর করে প্রক্রিয়াটি শেষ করে।
iOS 13 থেকে শুরু হওয়া Swift অ্যাপের জন্য, Signals API চালু করা হয়েছে, যা শুধু ব্যতিক্রম নয়, অপারেটিং সিস্টেম সিগন্যাল — SIGABRT, SIGSEGV এবং SIGBUS — ও হ্যান্ডল করে, যা হ্যান্ডলারের কভারেজ নিম্ন-স্তরের মেমরি ত্রুটিতে বাড়িয়ে দেয়।
বাস্তবায়ন iOS-এ বৈশ্বিক হ্যান্ডলারের জন্য NSSetUncaughtExceptionHandler এর মাধ্যমে C-ফাংশন সেট করা প্রয়োজন। হ্যান্ডলার একটি অপ্রক্রিয়াজাত ব্যতিক্রমের মুহূর্তে সমলয়ভাবে কল হয় এবং সম্পূর্ণ ত্রুটি প্রসঙ্গ গ্রহণ করে।
void handleUncaughtException(NSException exception) {
NSDictionary userInfo = [exception userInfo];
NSArray stackTrace = [exception callStackSymbols];
NSString reason = [exception reason];
// ক্র্যাশ লগ স্থানীয় ফাইলে সংরক্ষণ করুন
NSString logPath = [NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
[exceptionLog writeToFile:logPath atomically:YES];
}
int main(int argc, char argv[]) {
NSSetUncaughtExceptionHandler(&handleUncaughtException);
return UIApplicationMain(argc, argv, nil, nil);
}
iOS বাস্তবায়নের একটি গুরুত্বপূর্ণ বৈশিষ্ট্য: হ্যান্ডলার শুধুমাত্র Objective-C ব্যতিক্রম ধরে। throw-catch পদ্ধতি ব্যবহার করে Swift ত্রুটিগুলি এই হ্যান্ডলারে পৌঁছায় না — তাদের জন্য Swift Error Handling-এর মাধ্যমে পৃথক হ্যান্ডলিং প্রয়োজন। iOS 14 থেকে শুরু করে, Apple সর্বোচ্চ কভারেজের জন্য NSSetUncaughtExceptionHandler কে Signals API-এর সাথে সংযুক্ত করার পরামর্শ দেয়।
Apple Technical Note TN2151 অনুসারে, হ্যান্ডলার কল করার পর, অ্যাপকে 5 সেকেন্ড এর মধ্যে শেষ হতে হবে। হ্যান্ডলার থেকে ফিরে আসার পরে নির্বাহ চালিয়ে যাওয়ার যেকোনো প্রচেষ্টা অনির্ধারিত আচরণ এবং পুনরায় ক্র্যাশের দিকে নিয়ে যায়।
Android Thread.setDefaultUncaughtExceptionHandler এর মাধ্যমে বৈশ্বিক ব্যতিক্রম হ্যান্ডলিংয়ের জন্য আরও নমনীয় ব্যবস্থা প্রদান করে। হ্যান্ডলার যে থ্রেডে ব্যতিক্রম ঘটেছে তার রেফারেন্স এবং Throwable অবজেক্ট নিজেই গ্রহণ করে।
class GlobalExceptionHandler : Thread.UncaughtExceptionHandler {
override fun uncaughtException(thread: Thread, throwable: Throwable) {
// ক্র্যাশ লগ ফাইলে সংরক্ষণ করুন
val stackTrace = throwable.stackTraceToString()
val crashLog = "CRASH: ${thread.name}\n${stackTrace}"
val file = File(context.cacheDir, "crash_log.txt")
file.writeText(crashLog)
// Crashlytics-এ পাঠান
FirebaseCrashlytics.getInstance()
.recordException(throwable)
// প্রক্রিয়া শেষ করুন
android.os.Process.killProcess(
android.os.Process.myPid()
)
}
}
// Application.onCreate-এ সেটআপ
class App : Application() {
override fun onCreate() {
super.onCreate()
Thread.setDefaultUncaughtExceptionHandler(
GlobalExceptionHandler()
)
}
}
Android বাস্তবায়নের একটি মূল পার্থক্য: প্রতিটি থ্রেডের নিজস্ব হ্যান্ডলার থাকে, এবং setDefaultUncaughtExceptionHandler সেই সমস্ত থ্রেডের জন্য হ্যান্ডলার সেট করে যাদের ব্যক্তিগত হ্যান্ডলার নির্ধারিত নেই। এটি বৈশ্বিক কভারেজ নিশ্চিত করে — UI থ্রেড থেকে ব্যাকগ্রাউন্ড AsyncTask এবং করুটিন পর্যন্ত।
Android 12+-এ, একটি সীমাবদ্ধতা আছে: uncaughtException কল করার পর, অ্যাপকে 100 মিলিসেকেন্ড এর মধ্যে শেষ হতে হবে। যদি হ্যান্ডলার দীর্ঘস্থায়ী অপারেশন করে, সিস্টেম লগ লেখার আগেই প্রক্রিয়াটি বন্ধ করে দিতে পারে। ক্র্যাশ রিপোর্ট পাঠানোর জন্য ব্যাকগ্রাউন্ড সার্ভিস ব্যবহার করার পরামর্শ দেওয়া হয়।
প্রথম নিয়ম — অপ্রক্রিয়াজাত ব্যতিক্রমের পরে অ্যাপ অপারেশন পুনরুদ্ধারের চেষ্টা করবেন না। ক্র্যাশের পরে অ্যাপের অবস্থা অনির্ধারিত, এবং নির্বাহ চালিয়ে গেলে ব্যবহারকারীর ডেটা দূষিত হতে পারে।
সময় সীমা — Global Exception Handler-এর প্রধান প্রযুক্তিগত সীমাবদ্ধতা। iOS-এ এটি 5 সেকেন্ড, Android-এ — 100 মিলিসেকেন্ড। হ্যান্ডলারের ভিতরে, শুধুমাত্র ন্যূনতম ডেটা সেট সংরক্ষণ করা উচিত: ব্যতিক্রমের ধরন, কল স্ট্যাক এবং কিছু মূল ভেরিয়েবলের অবস্থা।
নেটওয়ার্ক অনুরোধ পাঠানো, ডাটাবেসে লেখা এবং জটিল সিরিয়ালাইজেশন বিলম্বিত পদ্ধতি-তে স্থানান্তরিত করা উচিত — উদাহরণস্বরূপ, লগ ফাইলে সংরক্ষণ করুন এবং পরবর্তী অ্যাপ লঞ্চে পাঠান।
ক্র্যাশ-রিপোর্টিং পরিষেবা — Firebase Crashlytics, Sentry, Bugsnag — তাদের নিজস্ব বৈশ্বিক হ্যান্ডলার সেট করে। যদি একজন ডেভেলপার শীর্ষে একটি কাস্টম হ্যান্ডলার সেট করে, তাদের নিজস্ব কাজের পরে ক্র্যাশ-রিপোর্টিং সিস্টেমে নিয়ন্ত্রণ দিতে হবে। Android-এ হ্যান্ডলার কম্পোজিশন ব্যবহার করা হয়: নিজের লজিক নির্বাহ করুন, তারপর পূর্ববর্তী হ্যান্ডলার কল করুন।
Firebase Crashlytics-এর জন্য, কাস্টম Thread.setDefaultUncaughtExceptionHandler একেবারেই না সেট করার পরামর্শ দেওয়া হয় — Crashlytics SDK ইনিশিয়ালাইজেশনে স্বয়ংক্রিয়ভাবে এটি করে।
ব্যবহারকারী প্রসঙ্গ — স্ট্যান্ডার্ড কল স্ট্যাক ছাড়াও, অ্যাপ সংস্করণ, OS সংস্করণ, উপলব্ধ মেমরি আকার এবং ক্র্যাশের আগে আপটাইম লগ করা উপযোগী। এই ডেটা সমস্যা পুনরুৎপাদন এবং সমাধানের জন্য অত্যন্ত গুরুত্বপূর্ণ।
iOS-এ, NSSetUncaughtExceptionHandler শুধু লেখার জন্যই নয়, NSUserDefaults-এ synchronize ফ্ল্যাগ সহ অস্থায়ী ডেটা স্টোরেজের জন্যও ব্যবহার করা যেতে পারে — যা তাৎক্ষণিক প্রক্রিয়া সমাপ্তিতেও স্থায়িত্ব নিশ্চিত করে।
বাধ্যতামূলক পরীক্ষা — Global Exception Handler-কে CI/CD-এর প্রতিটি ধাপে পরীক্ষা করা উচিত। iOS-এ, @throw NSException এর মাধ্যমে পরীক্ষামূলক ব্যতিক্রম ট্রিগার করা যেতে পারে, Android-এ — throw RuntimeException() এর মাধ্যমে। নিশ্চিত করুন যে হ্যান্ডলার কল হয়েছে, লগ সংরক্ষিত হয়েছে এবং অ্যাপ সঠিকভাবে শেষ হয়েছে।
Google I/O 2023 অনুসারে, উৎপাদনে 30% এর বেশি ক্র্যাশ সেই ডিভাইসে ঘটে যা ডেভেলপার পরীক্ষা করেনি — বিভিন্ন Android সংস্করণ, কাস্টম ফার্মওয়্যার, সীমিত মেমরি।
প্রথম এবং সবচেয়ে সাধারণ ভুল — ব্যতিক্রম হ্যান্ডল করার পরে অ্যাপ নির্বাহ চালিয়ে যাওয়ার চেষ্টা করা। uncaughtException কল করার পরে, অ্যাপ অস্থির অবস্থায় থাকে, এবং যেকোনো পরবর্তী অপারেশন ক্যাসকেডিং ত্রুটি এবং ডেটা দূষণের কারণ হতে পারে।
দ্বিতীয় ভুল — হ্যান্ডলারের ভিতরে দীর্ঘস্থায়ী অপারেশন করা। নেটওয়ার্ক অনুরোধ, বড় ফাইল লেখা বা জটিল গণনা প্রক্রিয়া জোর করে শেষ হওয়ার আগে সম্পূর্ণ হয় না। Apple Technical Q&A QA1468 অনুসারে, হ্যান্ডলারের ভিতরে HTTP অনুরোধ পাঠানোর চেষ্টা হারানো ক্র্যাশ রিপোর্টের প্রধান কারণ।
তৃতীয় ভুল — ব্যাকগ্রাউন্ড থ্রেড উপেক্ষা করা। শুধুমাত্র প্রধান থ্রেডের জন্য সেট করা Global Exception Handler করুটিন, DispatchQueue, AsyncTask বা RxJava-তে ক্র্যাশ থেকে রক্ষা করে না। Android-এ, প্রতিটি থ্রেডের নিজস্ব হ্যান্ডলার থাকা উচিত — এবং setDefaultUncaughtExceptionHandler শুধুমাত্র ব্যক্তিগত হ্যান্ডলার ছাড়া থ্রেডের জন্য এটি সমাধান করে।
চতুর্থ ভুল — OS সিগন্যালের জন্য ফলব্যাকের অভাব। iOS-এ NSSetUncaughtExceptionHandler SIGABRT, SIGSEGV এবং SIGBUS ধরে না। এই সিগন্যালগুলির জন্য sigaction API এর মাধ্যমে পৃথক হ্যান্ডলার সেটআপ প্রয়োজন। ডেভেলপাররা এটি তখনই জানতে পারে যখন অ্যাপ একটি ক্র্যাশ রিপোর্ট ছাড়াই ক্র্যাশ করে।
পঞ্চম ভুল — গোপনীয় ডেটা লগ করা। ক্র্যাশ লগে ইমেল, প্রমাণীকরণ টোকেন বা ব্যবহারকারীদের ব্যক্তিগত ডেটা আসতে পারে। এটি GDPR এবং Apple App Store Review Guidelines লঙ্ঘন করে। regex বা অনুমোদিত ফিল্ডের সাদাতালিকার মাধ্যমে প্রেরিত ডেটা সর্বদা ফিল্টার করুন।
সচরাচর জিজ্ঞাসিত প্রশ্ন
না — Global Exception Handler কল করার পরে, অ্যাপের অবস্থা অনির্ধারিত। নির্বাহ চালিয়ে যাওয়ার যেকোনো প্রচেষ্টা ডেটা দূষণের কারণ হতে পারে। একমাত্র সঠিক কাজ হল ক্র্যাশ লগ সংরক্ষণ করা এবং প্রক্রিয়া শেষ করা।
সব না — iOS-এ, NSSetUncaughtExceptionHandler শুধুমাত্র Objective-C ব্যতিক্রম ধরে। Swift ত্রুটি এবং OS সিগন্যাল (SIGSEGV, SIGABRT) পৃথক হ্যান্ডলার প্রয়োজন। Android-এ, Thread.setDefaultUncaughtExceptionHandler সব RuntimeExceptions ধরে কিন্তু JNI-এর মাধ্যমে নেটিভ কোড ত্রুটি ধরে না।
নিজের হ্যান্ডলার সেট করার আগে Thread.getDefaultUncaughtExceptionHandler() এর মাধ্যমে পূর্ববর্তী হ্যান্ডলার-এর রেফারেন্স সংরক্ষণ করুন। আপনার হ্যান্ডলারের শেষে, previousHandler.uncaughtException(thread, throwable) কল করুন — এটি নিশ্চিত করে যে Crashlytics বা Sentry তাদের ডেটা পায়।
নেটিভ কোডের জন্য, sigaction() এর মাধ্যমে সিগন্যাল হ্যান্ডলিং প্রয়োজন — SIGSEGV, SIGABRT, SIGBUS। Android-এ, আপনি Google Breakpad বা Crashpad ব্যবহার করতে পারেন। iOS-এ সংস্করণ 13 থেকে শুরু করে, mach ব্যতিক্রম হ্যান্ডল করার জন্য Signals API উপলব্ধ।
না — হ্যান্ডলার সেট করা শুধুমাত্র ব্যতিক্রম ঘটার মুহূর্তকে প্রভাবিত করে। সাধারণ অ্যাপ অপারেশনে, কোনো ওভারহেড নেই। একমাত্র ঝুঁকি হল মেমরি লিক যদি হ্যান্ডলার Activity বা Context-এর রেফারেন্স ধরে রাখে, যা আবর্জনা সংগ্রহ প্রতিরোধ করে।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন