سؤال

هذا السؤال لديه بالفعل إجابة هنا:

لقد طُلب مني إنشاء نظام جافا يتمتع بالقدرة على تحميل تعليمات برمجية جديدة (توسيعات) أثناء التشغيل.كيف يمكنني إعادة تحميل ملف jar أثناء تشغيل الكود الخاص بي؟أو كيف يمكنني تحميل جرة جديدة؟

من الواضح، نظرًا لأهمية وقت التشغيل المستمر، أود إضافة القدرة على إعادة تحميل الفصول الموجودة أثناء وجودها (إذا لم يؤدي ذلك إلى تعقيد الأمور كثيرًا).

ما هي الأشياء التي يجب أن أبحث عنها؟(فكر في الأمر كسؤالين مختلفين - أحدهما يتعلق بإعادة تحميل الفئات في وقت التشغيل، والآخر يتعلق بإضافة فئات جديدة).

هل كانت مفيدة؟

المحلول

من المحتمل أن يؤدي إعادة تحميل الفئات الموجودة بالبيانات الموجودة إلى كسر الأمور.

يمكنك تحميل تعليمات برمجية جديدة إلى أدوات تحميل الفئات الجديدة بسهولة نسبية:

ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL },
    getClass().getClassLoader()
);
Class<?> clazz = Class.forName("mypackage.MyClass", true, loader);
Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class);
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
doRun.run();

يمكن أن يتم تجميع البيانات المهملة التي لم تعد تستخدم أدوات تحميل الفئة (ما لم يكن هناك تسرب للذاكرة، كما هو الحال غالبًا عند استخدام برامج تشغيل ThreadLocal، وJDBC، java.beans, ، إلخ).

إذا كنت تريد الاحتفاظ ببيانات الكائن، فأنا أقترح عليك آلية الثبات مثل التسلسل، أو أي شيء اعتدت عليه.

بالطبع يمكن لأنظمة تصحيح الأخطاء القيام بأشياء أكثر روعة، ولكنها أكثر اختراقًا وأقل موثوقية.

من الممكن إضافة فئات جديدة إلى محمل الفئة.على سبيل المثال، باستخدام URLClassLoader.addURL.ومع ذلك، إذا فشل تحميل الفصل (لأنك، على سبيل المثال، لم تقم بإضافته)، فلن يتم تحميله أبدًا في مثيل محمل الفصل هذا.

نصائح أخرى

هذا يعمل بالنسبة لي:

File file  = new File("c:\\myjar.jar");

URL url = file.toURL();  
URL[] urls = new URL[]{url};

ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("com.mypackage.myclass");

لقد طُلب مني إنشاء نظام جافا يتمتع بالقدرة على تحميل تعليمات برمجية جديدة أثناء التشغيل

قد ترغب في بناء نظامك عليه OSGi (أو على الأقل خذ الكثير في هذا الأمر)، والذي تم إعداده خصيصًا لهذا الموقف.

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

لقد بحثت في Google قليلاً، ووجدت هذا الرمز هنا:

File file = getJarFileToLoadFrom();   
String lcStr = getNameOfClassToLoad();   
URL jarfile = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");    
URLClassLoader cl = URLClassLoader.newInstance(new URL[] {jarfile });   
Class loadedClass = cl.loadClass(lcStr);   

هل يمكن لأي شخص مشاركة الآراء/التعليقات/الإجابات بخصوص هذا النهج؟

استخدم org.openide.util.Lookup وClassLoader لتحميل البرنامج الإضافي Jar ديناميكيًا، كما هو موضح هنا.

public LoadEngine() {
    Lookup ocrengineLookup;
    Collection<OCREngine> ocrengines;
    Template ocrengineTemplate;
    Result ocrengineResults;
    try {
        //ocrengineLookup = Lookup.getDefault(); this only load OCREngine in classpath of  application
        ocrengineLookup = Lookups.metaInfServices(getClassLoaderForExtraModule());//this load the OCREngine in the extra module as well
        ocrengineTemplate = new Template(OCREngine.class);
        ocrengineResults = ocrengineLookup.lookup(ocrengineTemplate); 
        ocrengines = ocrengineResults.allInstances();//all OCREngines must implement the defined interface in OCREngine. Reference to guideline of implement org.openide.util.Lookup for more information

    } catch (Exception ex) {
    }
}

public ClassLoader getClassLoaderForExtraModule() throws IOException {

    List<URL> urls = new ArrayList<URL>(5);
    //foreach( filepath: external file *.JAR) with each external file *.JAR, do as follows
    File jar = new File(filepath);
    JarFile jf = new JarFile(jar);
    urls.add(jar.toURI().toURL());
    Manifest mf = jf.getManifest(); // If the jar has a class-path in it's manifest add it's entries
    if (mf
            != null) {
        String cp =
                mf.getMainAttributes().getValue("class-path");
        if (cp
                != null) {
            for (String cpe : cp.split("\\s+")) {
                File lib =
                        new File(jar.getParentFile(), cpe);
                urls.add(lib.toURI().toURL());
            }
        }
    }
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    if (urls.size() > 0) {
        cl = new URLClassLoader(urls.toArray(new URL[urls.size()]), ClassLoader.getSystemClassLoader());
    }
    return cl;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top