کلاس لودر
از آن برای تامین بایت کد کامپایل شده به JVM استفاده می شود که معمولاً در فایل هایی با پسوند ذخیره می شود.class
، اما می توان آن را از منابع دیگر نیز دریافت کرد، به عنوان مثال، از طریق شبکه دانلود شود یا توسط خود برنامه تولید شود. با توجه به مشخصات Java SE، برای اجرای کد در JVM، باید سه مرحله را طی کنید:
-
بارگذاری بایت کد از منابع و ایجاد نمونه ای از کلاس
Class
این شامل جستجوی کلاس درخواستی در بین کلاسهایی است که قبلاً بارگذاری شدهاند، دریافت بایت کد برای بارگیری و بررسی صحت آن، ایجاد نمونهای از کلاس
Class
(برای کار با آن در زمان اجرا)، و بارگیری کلاسهای والد. اگر کلاس ها و رابط های والد بارگذاری نشده باشند، کلاس مورد نظر بارگذاری نشده در نظر گرفته می شود. -
الزام آور (یا پیوند دادن)
با توجه به مشخصات، این مرحله به سه مرحله دیگر تقسیم می شود:
- تأیید ، صحت بایت کد دریافتی بررسی می شود.
- آماده سازی ، تخصیص RAM برای فیلدهای استاتیک و مقداردهی اولیه آنها با مقادیر پیش فرض (در این مورد، مقداردهی اولیه صریح، در صورت وجود، قبلاً در مرحله اولیه سازی رخ می دهد).
- وضوح ، تفکیک پیوندهای نمادین انواع، زمینه ها و روش ها.
-
مقداردهی اولیه شی دریافتی
در اینجا، برخلاف پاراگراف های قبلی، به نظر می رسد همه چیز روشن است که چه اتفاقی باید بیفتد. البته جالب است که بفهمیم دقیقاً چگونه این اتفاق می افتد.
- کلاس باید قبل از پیوند به طور کامل بارگذاری شود.
- یک کلاس قبل از شروع اولیه باید به طور کامل آزمایش و آماده شود.
- خطاهای رزولوشن پیوند در حین اجرای برنامه رخ می دهد، حتی اگر در مرحله پیوند شناسایی شده باشند.
انواع بارگذار جاوا
سه لودر استاندارد در جاوا وجود دارد که هر کدام یک کلاس را از یک مکان خاص بارگذاری می کنند:-
بوت استرپ یک لودر پایه است که به آن کلاس لودر اولیه نیز می گویند.
کلاس های استاندارد JDK را از بایگانی rt.jar بارگیری می کند
-
Extension ClassLoader – افزونه loader.
کلاس های برنامه افزودنی را بارگیری می کند، که به طور پیش فرض در فهرست jre/lib/ext قرار دارند، اما می توانند توسط ویژگی سیستم java.ext.dirs تنظیم شوند.
-
System ClassLoader – سیستم لودر.
کلاس های برنامه تعریف شده در متغیر محیطی CLASSPATH را بارگیری می کند
کلاس انتزاعی ClassLoader
هر لودر، به استثنای پایه یک، از نوادگان کلاس انتزاعی استjava.lang.ClassLoader
. به عنوان مثال، پیاده سازی بارگذار پسوند کلاس است sun.misc.Launcher$ExtClassLoader
و بارگذار سیستم است sun.misc.Launcher$AppClassLoader
. پایه لودر بومی است و پیاده سازی آن در JVM گنجانده شده است. هر کلاسی که گسترش یابد java.lang.ClassLoader
می تواند راه خود را برای بارگذاری کلاس ها با بلک جک و همین موارد ارائه دهد. برای انجام این کار، لازم است روش های مربوطه را دوباره تعریف کنیم، که در حال حاضر فقط می توانم آنها را به صورت سطحی در نظر بگیرم، زیرا من این موضوع را با جزئیات متوجه نشدم. آن ها اینجا هستند:
package java.lang;
public abstract class ClassLoader {
public Class<?> loadClass(String name);
protected Class<?> loadClass(String name, boolean resolve);
protected final Class<?> findLoadedClass(String name);
public final ClassLoader getParent();
protected Class<?> findClass(String name);
protected final void resolveClass(Class<?> c);
}
loadClass(String name)
یکی از معدود متدهای عمومی که نقطه ورود برای بارگذاری کلاس ها است. اجرای آن به فراخوانی روش محافظت شده دیگری خلاصه می شود loadClass(String name, boolean resolve)
که باید نادیده گرفته شود. اگر به Javadoc این روش محافظت شده نگاه کنید، می توانید چیزی شبیه به زیر را درک کنید: دو پارامتر به عنوان ورودی ارائه می شود. یکی نام باینری کلاس (یا نام کلاس کاملاً واجد شرایط) است که باید بارگذاری شود. نام کلاس با لیستی از تمام بسته ها مشخص می شود. پارامتر دوم یک پرچم است که تعیین می کند که آیا وضوح پیوند نمادین مورد نیاز است یا خیر. به طور پیش فرض false است ، به این معنی که از بارگذاری کلاس تنبل استفاده می شود. علاوه بر این، با توجه به مستندات، در اجرای پیشفرض متد، یک فراخوانی برقرار میشود findLoadedClass(String name)
که بررسی میکند که آیا کلاس قبلاً بارگذاری شده است یا خیر و اگر چنین است، یک مرجع به این کلاس برمیگرداند. در غیر این صورت، متد کلاس بارگذاری بارگذار مادر فراخوانی می شود. اگر هیچ یک از لودرها نتوانستند یک کلاس بارگذاری شده را پیدا کنند، هر یک از آنها، به ترتیب معکوس، سعی میکنند آن کلاس را پیدا کرده و بارگذاری کنند، و از رده خارج میشوند findClass(String name)
. این موضوع با جزئیات بیشتر در فصل "طرح بارگذاری کلاس" مورد بحث قرار خواهد گرفت. و در نهایت، در نهایت، پس از بارگیری کلاس، بسته به پرچم حل ، تصمیم گیری می شود که آیا کلاس ها از طریق پیوندهای نمادین بارگیری شوند یا خیر. یک مثال واضح این است که مرحله Resolution را می توان در مرحله بارگذاری کلاس فراخوانی کرد. بر این اساس، با گسترش کلاس ClassLoader
و نادیده گرفتن متدهای آن، لودر سفارشی می تواند منطق خود را برای تحویل بایت کد به ماشین مجازی پیاده سازی کند. جاوا همچنین از مفهوم بارگذار کلاس "جاری" پشتیبانی می کند. لودر فعلی همان لودری است که کلاس در حال اجرا را بارگذاری کرده است. هر کلاس می داند که با کدام لودر بارگذاری شده است، و شما می توانید با تماس با آن، این اطلاعات را دریافت کنید String.class.getClassLoader()
. برای همه کلاس های برنامه، لودر "جاری" معمولاً یک سیستم است.
سه اصل بارگذاری کلاس
-
هیئت نمایندگی
درخواست بارگیری کلاس به بارگذار والد ارسال می شود و تلاش برای بارگیری خود کلاس تنها در صورتی انجام می شود که بارگذار والد نتواند کلاس را پیدا و بارگذاری کند. این رویکرد به شما اجازه می دهد تا کلاس ها را با لودری که تا حد امکان نزدیک به پایه است بارگیری کنید. این به حداکثر دید کلاس می رسد. هر لودر یک رکورد از کلاس هایی که توسط خود بارگذاری شده اند را نگه می دارد و آنها را در حافظه پنهان خود قرار می دهد. به مجموعه این کلاس ها scope می گویند.
-
دید
لودر فقط کلاسهای «خود» و کلاسهای «والد» را میبیند و هیچ ایدهای درباره کلاسهایی که توسط «فرزند» بارگیری شدهاند ندارد.
-
منحصر به فرد بودن
یک کلاس فقط یک بار می تواند بارگذاری شود. مکانیسم تفویض اطمینان حاصل می کند که بارگیری که بارگذاری کلاس را آغاز می کند، کلاسی را که قبلاً در JVM بارگذاری شده بود بارگذاری نمی کند.
طرح بارگذاری کلاس
هنگامی که یک فراخوان برای بارگیری یک کلاس اتفاق می افتد، این کلاس در حافظه پنهان کلاس های بارگیری شده فعلی بارگیری می شود. اگر کلاس مورد نظر قبلا بارگذاری نشده باشد، اصل تفویض اختیار، کنترل را به بارگذار والد که یک سطح بالاتر در سلسله مراتب قرار دارد، منتقل می کند. بارگذار والد نیز سعی می کند کلاس مورد نظر را در حافظه پنهان خود پیدا کند. اگر کلاس قبلاً بارگذاری شده باشد و لودر مکان آن را بداند، یک شیClass
از آن کلاس برگردانده می شود. اگر نه، جستجو تا زمانی که به بوت لودر پایه برسد ادامه خواهد یافت. اگر بارگذار پایه اطلاعاتی در مورد کلاس مورد نیاز نداشته باشد (یعنی هنوز بارگذاری نشده باشد)، بایت کد این کلاس در محل کلاس هایی که لودر داده شده از آنها اطلاع دارد جستجو می شود و اگر کلاس نتواند بارگذاری شود، کنترل به بارگذار فرزند باز می گردد، که سعی می کند از منابع شناخته شده بارگیری کند. همانطور که در بالا ذکر شد، مکان کلاسها برای بارگذار پایه کتابخانه rt.jar است، برای بارکننده افزونه - دایرکتوری با پسوندهای jre/lib/ext، برای سیستم یک - CLASSPATH، برای کاربر یکی میتواند چیزی متفاوت باشد. . بنابراین، پیشرفت کلاس های بارگیری در جهت مخالف - از بارگذار ریشه به بارگذاری فعلی می رود. وقتی بایت کد کلاس پیدا شد، کلاس در JVM بارگذاری می شود و نمونه ای از نوع به دست می آید Class
. همانطور که به راحتی می توانید مشاهده کنید، طرح بارگذاری توصیف شده مشابه روش اجرای فوق است loadClass(String name)
. در زیر می توانید این نمودار را در نمودار مشاهده کنید.
به عنوان نتیجه گیری
در اولین مراحل یادگیری زبان، نیاز خاصی به درک نحوه بارگذاری کلاس ها در جاوا وجود ندارد، اما دانستن این اصول اولیه به شما کمک می کند در مواجهه با خطاهایی مانندClassNotFoundException
یا NoClassDefFoundError
. خوب، یا حداقل تقریباً درک کنید که ریشه مشکل چیست. بنابراین، یک استثنا ClassNotFoundException
زمانی رخ می دهد که یک کلاس در حین اجرای برنامه به صورت پویا بارگذاری شود، زمانی که لودرها نمی توانند کلاس مورد نیاز را در حافظه پنهان یا در طول مسیر کلاس پیدا کنند. اما این خطا NoClassDefFoundError
بحرانی تر است و زمانی رخ می دهد که کلاس مورد نیاز در حین کامپایل در دسترس بود، اما در هنگام اجرای برنامه قابل مشاهده نبود. اگر برنامه فراموش کند کتابخانه ای را که استفاده می کند شامل شود، ممکن است اتفاق بیفتد. خوب، همین واقعیت درک اصول ساختار ابزاری که در کار خود استفاده می کنید (الزاماً غوطه ور شدن واضح و دقیق در اعماق آن) به درک فرآیندهای رخ داده در این مکانیسم شفافیت می بخشد، که در به نوبه خود، منجر به استفاده مطمئن از این ابزار می شود.
GO TO FULL VERSION