logo

ClassLoader في جافا

جافا كلاسلوادر

Java ClassLoader هي فئة مجردة. ينتمي إلى أ java.lang طَرد. يقوم بتحميل الفئات من موارد مختلفة. يتم استخدام Java ClassLoader لتحميل الفئات في وقت التشغيل. بمعنى آخر، يقوم JVM بتنفيذ عملية الربط في وقت التشغيل. يتم تحميل الفصول الدراسية في JVM حسب الحاجة. إذا كانت الفئة المحملة تعتمد على فئة أخرى، فسيتم تحميل تلك الفئة أيضًا. عندما نطلب تحميل فصل دراسي، فإنه يقوم بتفويض الفصل إلى الأصل الخاص به. بهذه الطريقة، يتم الحفاظ على التفرد في بيئة وقت التشغيل. من الضروري تنفيذ برنامج جافا.

مدة جافا
ClassLoader في جافا

يعتمد Java ClassLoader على ثلاثة مبادئ: وفد , الرؤية ، و التفرد .

    مبدأ التفويض:يقوم بإعادة توجيه طلب تحميل الفئة إلى محمل الفئة الأصل. يقوم بتحميل الفصل فقط إذا لم يعثر الوالد على الفصل أو يقوم بتحميله.مبدأ الرؤية:يسمح لمحمل الفئة الفرعية برؤية جميع الفئات التي تم تحميلها بواسطة ClassLoader الأصلي. لكن مُحمل الفئة الأصل لا يمكنه رؤية الفئات المحملة بواسطة مُحمل الفئة الفرعية.مبدأ التفرد:يسمح بتحميل الفصل مرة واحدة. ويتم تحقيق ذلك من خلال مبدأ التفويض. فهو يضمن عدم قيام ClassLoader الفرعي بإعادة تحميل الفصل الذي تم تحميله بالفعل بواسطة الوالدين.

أنواع ClassLoader

في Java، يكون لكل ClassLoader موقع محدد مسبقًا حيث يتم تحميل ملفات الفصل منه. هناك الأنواع التالية من ClassLoader في Java:

محمل فئة Bootstrap: يقوم بتحميل ملفات فئة JDK القياسية من rt.jar والفئات الأساسية الأخرى. إنه أحد الوالدين لجميع محمل الفئة. ليس لديها أي والد. عندما نستدعي String.class.getClassLoader() فإنه يُرجع قيمة خالية، وأي كود يعتمد عليها يُلقي NullPointerException. ويسمى أيضًا Primordial ClassLoader. يقوم بتحميل ملفات الفئة من jre/lib/rt.jar. على سبيل المثال، فئة الحزمة Java.lang.

محمل فئة الملحقات: يقوم بتفويض طلب تحميل الفئة إلى الأصل. إذا لم ينجح تحميل الفصل، فسيتم تحميل الفئات من دليل jre/lib/ext أو أي دليل آخر مثل java.ext.dirs. يتم تنفيذه بواسطة sun.misc.Launcher$ExtClassLoader في JVM.

محمل فئة النظام: يقوم بتحميل فئات خاصة بالتطبيق من متغير البيئة CLASSPATH. يمكن ضبطه أثناء استدعاء البرنامج باستخدام خيارات سطر الأوامر -cp أو classpath. إنه تابع لملحق ClassLoader. يتم تنفيذه بواسطة فئة sun.misc.Launcher$AppClassLoader. كل Java ClassLoader ينفذ java.lang.ClassLoader.

ClassLoader في جافا

كيف يعمل ClassLoader في جافا

عندما يطلب JVM فئة ما، فإنه يستدعي طريقةloadClass() للفئة java.lang.ClassLoader عن طريق تمرير الاسم المصنف بالكامل للفئة. تستدعي طريقة LoadClass () طريقة findLoadedClass () للتحقق من أن الفصل قد تم تحميله بالفعل أم لا. مطلوب لتجنب تحميل الفصل عدة مرات.

إذا تم تحميل الفصل بالفعل، فإنه يقوم بتفويض الطلب إلى ClassLoader الأصل لتحميل الفصل. إذا لم يتمكن ClassLoader من العثور على الفئة، فإنه يستدعي طريقة findClass() للبحث عن الفئات في نظام الملفات. يوضح الرسم البياني التالي كيفية تحميل ClassLoader للفئة في Java باستخدام التفويض.

ClassLoader في جافا

لنفترض أن لدينا فئة معينة من التطبيقات Demo.class. يتم نقل طلب تحميل ملفات هذه الفئة إلى تطبيق ClassLoader. يقوم بتفويض ملحق ClassLoader الأصلي الخاص به. علاوة على ذلك، فإنه يفوض إلى Bootstrap ClassLoader. ابحث في Bootstrap عن هذا الفصل في rt.jar وبما أن هذا الفصل غير موجود. اطلب الآن النقل إلى Extension ClassLoader الذي يبحث عن الدليل jre/lib/ext ويحاول تحديد موقع هذه الفئة هناك. إذا تم العثور على الفئة هناك، فسيقوم ملحق ClassLoader بتحميل تلك الفئة. لا يقوم تطبيق ClassLoader بتحميل هذه الفئة مطلقًا. عندما لا يقوم الملحق ClassLoader بتحميله، يقوم التطبيق ClaasLoader بتحميله من CLASSPATH في Java.

ينص مبدأ الرؤية على أن ClassLoader الفرعي يمكنه رؤية الفصل الذي تم تحميله بواسطة ClassLoader الأصلي، ولكن العكس غير صحيح. وهذا يعني أنه إذا قام Application ClassLoader بتحميل Demo.class، ففي مثل هذه الحالة، فإن محاولة تحميل Demo.class بشكل صريح باستخدام ملحق ClassLoader يؤدي إلى java.lang.ClassNotFoundException.

وفقًا لمبدأ التفرد، لا ينبغي تحميل الفئة التي تم تحميلها من قبل الوالدين بواسطة Child ClassLoader مرة أخرى. لذلك، من الممكن كتابة محمل الفصل الذي ينتهك مبادئ التفويض والتفرد ويقوم بتحميل الفصل بنفسه.

باختصار، يتبع مُحمل الفئة القاعدة التالية:

  • يتحقق مما إذا تم تحميل الفصل بالفعل.
  • إذا لم يتم تحميل الفصل، فاطلب من محمل الفصل الأصلي تحميل الفصل.
  • إذا لم يتمكن مُحمل الفئة الأصل من تحميل الفئة، فحاول تحميلها في مُحمل الفئة هذا.

خذ بعين الاعتبار المثال التالي:

 public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } } 

ترجمة وتشغيل التعليمات البرمجية أعلاه باستخدام الأمر التالي:

 javac Demo.java java -verbose:class Demo 

-مطول:الطبقة: يتم استخدامه لعرض المعلومات حول الفئات التي يتم تحميلها بواسطة JVM. يكون ذلك مفيدًا عند استخدام أداة تحميل الفئة لتحميل الفئات ديناميكيًا. ويبين الشكل التالي الإخراج.

ClassLoader في جافا

يمكننا ملاحظة أن فئات وقت التشغيل التي تتطلبها فئة التطبيق (Demo) يتم تحميلها أولاً.

عندما يتم تحميل الفصول

هناك حالتان فقط:

  • عندما يتم تنفيذ رمز البايت الجديد.
  • عندما يقوم رمز البايت بإشارة ثابتة إلى الفصل الدراسي. على سبيل المثال، System.out .

التحميل الثابت مقابل التحميل الديناميكي للفئة

يتم تحميل الفئات بشكل ثابت باستخدام عامل التشغيل 'الجديد'. يستدعي التحميل الديناميكي للفئة وظائف مُحمل الفئة في وقت التشغيل باستخدام طريقة Class.forName().

الفرق بين LoadClass() و Class.forName()

تقوم طريقةloadClass() بتحميل الفئة فقط ولكنها لا تقوم بتهيئة الكائن. بينما تقوم طريقة Class.forName() بتهيئة الكائن بعد تحميله. على سبيل المثال، إذا كنت تستخدم ClassLoader.loadClass() لتحميل برنامج تشغيل JDBC، فإن أداة تحميل الفئة لا تسمح بتحميل برنامج تشغيل JDBC.

يقوم الأسلوب java.lang.Class.forName() بإرجاع كائن الفئة مقترنًا بالفئة أو الواجهات التي تحمل اسم السلسلة المحدد. يقوم بطرح ClassNotFoundException إذا لم يتم العثور على الفصل.

مثال

في هذا المثال، تم تحميل فئة java.lang.String. يقوم بطباعة اسم الفئة واسم الحزمة وأسماء جميع الطرق المتاحة لفئة السلسلة. نحن نستخدم Class.forName() في المثال التالي.

فصل: يمثل كائن فئة يمكن أن يكون من أي نوع (؟ هو حرف بدل). يحتوي نوع الفصل على معلومات تعريفية حول الفصل الدراسي. على سبيل المثال، نوع String.class هو Class. استخدم Class إذا كان الفصل الذي يتم تصميمه غير معروف.

getDeclaredMethod(): تقوم بإرجاع مصفوفة تحتوي على كائنات الطريقة التي تعكس كافة الأساليب المعلنة للفئة أو الواجهة التي يمثلها كائن الفئة هذا، بما في ذلك الوصول العام والمحمي والافتراضي (الحزمة) والطرق الخاصة، ولكن باستثناء الطرق الموروثة.

الحصول على الاسم (): تقوم بإرجاع اسم الطريقة الذي يمثله كائن الطريقة هذا، كسلسلة.

 import java.lang.reflect.Method; public class ClassForNameExample { public static void main(String[] args) { try { Class cls = Class.forName('java.lang.String'); System.out.println('Class Name: ' + cls.getName()); System.out.println('Package Name: ' + cls.getPackage()); Method[] methods = cls.getDeclaredMethods(); System.out.println('-----Methods of String class -------------'); for (Method method : methods) { System.out.println(method.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 

انتاج |

 Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access0 access0