Classloader در جاوا چیست؟ — شرح مفهوم بارگذارنده کلاس جاوا به بیان ساده

Classloader در جاوا یا «Java Class Loader» که می‌توان آن را «بارگذارنده کلاس جاوا» ترجمه کرد، بخشی از محیط زمان اجرای جاوا (Java Runtime Environment) در برنامه نویسی به حساب می‌آید که کلاس‌های جاوا را به صورت پویا داخل ماشین مجازی جاوا (Java Virtual Machine) بارگذاری می‌کند. کلاس‌ها معمولاً در زمان نیاز و هنگام تقاضا (On Demand) بارگذاری می‌شوند. سیستم زمان اجرای جاوا نیازی به داشتن اطلاعات در خصوص فایل‌ها ندارد؛ چرا که این مسئله به بارگذارنده کلاس یا همان Class Loader واگذار (Delegate) شده است.

Class loader در جاوا

Class Loader در جاوا چیست؟

یک کتابخانه نرم افزاری، مجموعه‌ای از کدهای شی مرتبط به حساب می‌آید. در زبان برنامه نویسی جاوا، کتابخانه‌ها معمولاً در فایل‌هایی از نوع JAR بسته‌بندی می‌شوند. کتابخانه‌ها می‌توانند شامل اشیایی با نوع‌های مختلف باشند. مهم‌ترین نوع از شیئی که در فایل JAR قرار می‌گیرد، «کلاس جاوا» است. کلاس را می‌توان به عنوان یک واحد نام‌گذاری شده از کدها در نظر گرفت. بارگذارنده کلاس، مسئولیت موقعیت‌یابی کتابخانه‌ها، خواندن محتوای آن‌ها و بارگذاری کلاس مورد نظر را از داخل کتابخانه‌ها بر عهده دارد. این نوع بارگذاری معمولاً بر حسب تقاضا یا همان «On-Demand» انجام می‌شود. در این حالت، تا زمانی که کلاس توسط برنامه فراخوانی نشود، بارگذاری انجام نخواهد شد. یک کلاس با نام مشخص تنها یک بار توسط یک بارگذارنده کلاس مشخص قابل فراخوانی است.

هر کلاس جاوا باید به وسیله یک بارگذارنده کلاس فراخوانی شود. علاوه بر این، برنامه‌های جاوا ممکن است از کتابخانه‌های خارجی (External Library) هم استفاده کنند. کتابخانه‌های خارجی، کتابخانه‌هایی هستند که توسط شخصی به غیر از سازنده برنامه نوشته شده‌اند. همچنین، حداقل در بخشی‌هایی برنامه‌های جاوا ممکن است از چند کتابخانه استفاده شود.

انواع Class Loader در جاوا چیست؟

وقتی که ماشین مجازی جاوا شروع به کار می‌کند، از سه بارگذارنده کلاس استفاده می‌شود:

  1. بارگذارنده کلاس Bootstrap
  2. بارگذارنده کلاس Extensions (افزونه‌ها)
  3. بارگذارنده کلاس سیستم

انواع Class Loader در جاوا چیست؟

بارگذارنده کلاس Bootstrap

بارگذارنده کلاس Bootstrap کتابخانه‌های هسته‌ای جاوا را بارگذاری می‌کند که در شاخه «<JAVA_HOME>/jre/lib» قرار گرفته‌اند. این Class Loader که جزئی از ماشین مجازی هسته‌ای جاوا به حساب می‌آید، با کدهای بومی (Native Code) نوشته شده است.

بارگذارنده کلاس Extensions

بارگذارنده کلاس Extensions کدهایشاخه Extensions یعنی آدرس «<JAVA_HOME>/jre/lib/ext» یا هر محل دیگری که توسط خصوصیت سیستمی java.ext.dirs مشخص شده است را بارگذاری می‌کند.

بارگذارنده کلاس سیستم

در نهایت، بارگذارنده کلاس سیستم هم کدهایی را بارگذاری می‌کند که در java.class.path قرار دارند که به متغیر محیطی CLASSPATH نگاشت می‌شود.

Class Loader های تعریف شده توسط کاربر

Class Loader جاوا به وسیله زبان برنامه نویسی جاوا نوشته شده است. بنابراین، امکان ایجاد Class Loader بدون درک جزئیات ماشین مجازی جاوا وجود دارد. هر Class Loader جاوا دارای یک بارگذارنده کلاس والد است. این بارگذارنده کلاس والد زمانی تعریف می‌شود که یک بارگذارنده جدید نمونه‌سازی شده است. همچنین بارگذارنده والد می‌تواند همان بارگذارنده کلاس سیستم پیش‌فرض ماشین مجازی باشد. این مسئله باعث می‌شود که مثلا بتوان کارهای زیر را انجام داد:

  • کلاس‌ها را در زمان اجرا بارگذاری یا تخلیه (Unload) کرد. مثلاً این قابلیت برای بارگذاری کتابخانه‌ها به صورت پویا در زمان اجرا حتی از یک منبع HTTP قابل استفاده است. این ویژگی بسیار مهمی برای موارد زیر به حساب می‌آید:
    • پیاده‌سازی زبان‌های اسکریپتی مثل Jython
    • استفاده از Bean Builderها
    • فراهم شدن امکان توسعه پذیری (Extensibility)
    • فراهم شدن امکان تعریف چندین فضای نام (Namespace) برای ارتباط برقرار کردن
  • برای تغییر دادن نحوه بارگذاری بایت کد (Bytecode)؛ برای مثال امکان استفاده از بایت کد کلاس جاوای کدگذاری شده فراهم شده است.
  • برای ویرایش بایت کدهای بارگذاری شده. مثلاً برای «بافت جنبه‌های زمان بارگذاری» (Load Time Weaving) در زمان استفاده از برنامه نویسی جنبه گرا (Aspect Oriented Programming)

Class Loader ها در Jakarta EE

سرورهای اپلیکیشن Jakarta EE که قبلاً با نام Java EE و J2EE شناخته می‌شد، معمولاً کلاس‌ها را از یک آرشیو WAR یا EAR به وسیله درختی از class loaderها بارگذاری می‌کند. این کار باعث می‌شود که اپلیکیشن از سایر برنامه‌های کاربردی جدا و ایزوله شود، اما کماکان کلاس‌ها بین ماژول‌های مستقر شده به اشتراک گذاشته شوند. به اصطلاح، «کانتینرهای Servlet» معمولاً از نقطه نظر چندین بارگذارنده کلاس پیاده‌سازی می‌شوند.

JAR Hell چیست ؟

JAR hell اصطلاحی مشابه DLL hell است که برای توصیف تمام راه‌های مختلفی استفاده می‌شود که فرآیند بارگذاری کلاس می‌تواند در آن به عدم کارکرد منجر شود. JAR hell در سه حالت اتفاق می‌افتد که این حالت‌ها در ادامه شرح داده شده‌اند:

  • حضور تصادفی دو نسخه مختلف از یک کتابخانه یکسان نصب شده روی سیستم می‌تواند منجر به بروز JAR hell شود. این یک خطا توسط سیستم به حساب نخواهد آمد. به جای آن، سیستم کلاس‌ها را از یکی از این کتابخانه‌های بارگذاری خواهد کرد. اضافه کردن کتابخانه جدید به فهرست کتابخانه‌های در دسترس به جای جایگزین کردن آن می‌تواند باعث شود اپلیکیشن همچنان به گونه‌ای عمل کند که گویی کتابخانه قدیمی در حال استفاده است.
  • ممکن است چندین کتابخانه یا اپلیکیشن مختلف به نسخه‌های مختلفی از یک کتابخانه نیاز داشته باشند. در صورتی که در نسخه‌های مختلف آن کتابخانه از نام‌های کلاس یکسانی استفاده شده باشد، هیچ راهی برای بارگذاری نسخه‌های آن کتابخانه با یک بارگذارنده کلاس یکسان وجود نخواهد داشت.
  • پیچیده‌ترین مشکلات JAR hell در شرایطی رخ می‌دهند که نیاز به بهره‌برداری از تمام پیچیدگی‌های سیستم بارگذاری کلاس وجود داشته باشد. لازم نیست که یک برنامه جاوا تنها از یک Class Loader استفاده کند، بلکه در عوض ممکن است یک برنامه جاوا از تعداد زیادی بارگذارنده کلاس تو در تو همکار تشکیل شده باشد. کلاس‌هایی که به وسیله Class Loaderهای مختلف بارگذاری می‌شوند به روش‌های پیچیده‌ای با هم تعامل می‌کنند که ممکن است به طور کامل توسط یک توسعه دهنده قابل درک نباشند. این مسئله منجر به بروز خطاها یا رخنه‌هایی (باگ‌هایی) می‌شود که تجزیه-تحلیل، توضیح و رفع آن‌ها دشوار است.

در موافقتنامه OSGi یک فریم ورک پیمانه‌مندی JAR hell برای ماشین‌های مجازی فعلی و آینده SE ،ME و EE مشخص شده است که به طور گسترده‌ای مورد استفاده قرار می‌گیرد. استفاده از فراداده‌ها در مانیفست JAR (که به آن‌ها Bundle گفته می‌شود) بر پایه‌ای مبتنی بر بسته (Per-Package) مخابره می‌شوند. باندل‌ها می‌توانند بسته‌ها را استخراج کنند، آن‌ها را وارد کنند و بسته‌ها را خصوصی نگه دارند که باعث می‌شود امکان استفاده از ساختارهای پایه پیمانه‌مندی و مدیریت متعلقات نسخه‌بندی شده فراهم شود.

اقدامات انجام شده برای جلوگیری از وقوع JAR Hell

برای رفع مشکلات مربوط به JAR Hell در سال ۲۰۰۵ میلادی، فرآیند به نام «روند جامعه جاوا» (Java Community Process) یا همان JSR 277 شروع به کار کرد. راهکار «سیستم ماژولی پلتفرم جاوا» (Java Platform Module System) با هدف معرفی یک قالب توزیعی جدید یعنی یک طرح نسخه‌بندی ماژول و یک مخزن مازول‌های مشترک (مشابه کش اسمبلی سراسری یا همان Global Assembly Cache در دات نت مایکروسافت) ارائه شد. در سال ۲۰۰۸، شرکت سان اعلام کرد که JSR 277 معلق شده است.

سیستم ماژول جاوا بعداً با نام پروژه‌ Jigsaw مجدداً ارائه شد که در جاوای ۹ هم گنجانده شده است. این محصول با نام «سیستم ماژول پلتفرم جاوا» در سال ۲۰۱۷ منتشر شده است و پشتیبانی از نرم افزار پیمانه‌بندی شده را شامل می‌شود. این سیستم در سطح منبع با فایل‌های module-info.java مدیریت و کنترل می‌شود. سیستم پیمانه‌مند جاوا فلسفه متفاوتی را نسبت به معماری OSGi دنبال می‌کند و ارائه پیمانه‌مندی برای محیط زمان اجرای جاوا را به روشی با سازگاری رو به عقب فراهم می‌کند که از ساز و کار پیش‌فرض بارگذاری کلاس‌هایی فراهم شده به وسیله JRE استفاده می‌کند. اگر چه، با توجه به اینکه سیستم ماژولی جاوا امکان هم‌زیستی کنترل شده کتابخانه‌های یکسان با نسخه‌های متفاوت را فراهم نمی‌کند، برای مقابله با معزل JAR Hell مناسب نیست.

جمع‌بندی

در این مقاله به شرح چیستی بارگذارنده کلاس جاوا (Java Class Loader) پرداخته و نحوه عملکرد آن توضیح داده شد. همچنین پیرامون سایر مباحث مربوط به Class Loader در جاوا، نظیر انواع آن و JAR Hell نیز بحث شد. امید است این مقاله مفید واقع شود.

اگر این مطلب مفید بوده است، استفاده از دوره‌های آموزشی و مطالب زیر نیز پیشنهاد می‌شوند:

 

منبع [+]

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *