السلام عليكــم ورحمـة الله وبركاتــه ،،
الكلاس ClassLoader هي المسؤولة عن البحث عن الملفات class التي تحتوي على الكلاسات التي سنستعملها في برامجنا، وتحميل هاته الكلاسات في الذاكرة
التصرف الطبيعي للClassLoader هو البحث عن ملفات class في القرص الصلب، وبالخصوص في المجلدات الموجودة في الclasspath
ماذا لو كنا نريد اساخدام كلاس يوجد في خادم ما؟؟ ما العمل؟؟
سنقوم بكتابة ClassLoader خاص بنا، بحيث يقوم بتحميل الكلاس من الخادم
أولا فلنتكلم قليلا عن الكلاس ClassLoader
عندما تحتاج الJVM إلى كلاس ما، فإن الClassLoader يقوم بالخطوات التالية
1-- ينادي على الميثود findLoadedClassللتأكد من أن هذه الكلاس لم يتم تحميلها من قبل
2-- إذا لم تنجح المرحلة الأولى في إيجاد الكلاس المراد، ينادي الClassLoader على الميثود loadClass الخاصة بالdefault ClassLoader أي الClassLoader العادي الذي يستعمل دائما
3-- إذا لم تنجح المرحلة الثانية، فإن المرحلة الأخيرة هي النداء على الميثود findClass، إذا لم يتم إيجاد الكلاس فإنه يتم إرسال ClassNotFoundException
كل كلاس ترث من ClassLoader يجب عليها أن تعيد كتابة الميثود findClass وفيها نحدد طريقة البحث عن الكلاس
الآن مع التطبيق. لدينا كلاس Test يوجد في هذا العنوان http://herch.heliohost.org/Test.class ونريد طبعا عمل instance لهذه الكلاس داخل برنامجنا
أولا الClassLoader الذي أعدنا فيه كتابة الميثود findClass
import java.net.*;
public class MyClassLoader extends ClassLoader {
protected Class findClass(String name)
throws ClassNotFoundException {
if (name.equals("Test")) {
InputStream input = null;
try {
URL urlClass = new URL("http://herch.heliohost.org/Test.class");
input = urlClass.openStream();
byte[] classData = new byte[input.available()];
input.read(classData);
return defineClass(name, classData, 0, classData.length);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
throw new ClassNotFoundException();
}
}
import java.io.*;
ماذا يفعل هذا الكود؟ أولا نقوم بفتح stream ونقرأ الملف class، ثم نخزن هذا المحتوى داخل مصفوفة byte. الآن لدينا مصفوفة من صنف byte، لكننا بحاجة إلى كلاس من صنف Class لأن الميثود findClass يجب أن تعيد Class object، هذا هو الهدف من استعمال الميثود defineClass، فهذه الميثود تنتظر أربع arguments، الأول هو إسم الكلاس، الثاني هو المصفوفة التي تحتوي على محتوى الكلاس، الarguments الثالث والرابع هما نقطتا البداية والنهاية بالنسبة للقراءة من المصفوفة، والناتج يكون Class object
الآن لدينا الClassLoader فكيف سنستعمله داخل البرنامج؟
public class TestClassLoader {
public static void main(String[] args) {
MyClassLoader loader = new MyClassLoader();
try {
Class c = loader.loadClass("Test");
Object o = c.newInstance();
Method m1 = c.getMethod("sayHello", null);
Method m2 = c.getMethod("sayBye", null);
Method m3 = c.getMethod("saySalam", null);
m1.invoke(o, null);
m2.invoke(o, null);
m3.invoke(o, null);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
import java.lang.reflect.*;
الكلاس Test تحتوي على 3 methods، sayHello & sayBye & saySalamوهما اللتان يتم النداء عليهما عن طريق invoke
عند عمل compile للبرنامج، فتحصلون على بعض الإنذارات، وذلك ناتج عن الnull الذي نمرر لinvoke و getMethod. يمكن إزالة الإنذارات بواسطة الoption -nowarn
بالنسبة لملف الكلاس، فهو موجود فعلا في العنوان المستعمل ويمكنكم التجربة به، أو يمكنكم التجربة بعنوان آخر


