2013-08-22 2 views
0

У меня есть новый небольшой проект Swing, мне нужно загрузить тот же класс из двух разных jarsm, эти банки являются сторонними, поэтому у меня нет исходного кода.Загрузка того же класса из разных банок

например, мне нужно загрузить myClass из двух банок. jar1.jar jar2.jar

просто я то, что мне нужно сделать:

public void doMyClassLogicVersion1() { 

    Loader = // here i need to load jar1.myClass. 
    // myClass need a two params to initialize it in the normal case 
    // also i need to access its static members 
    // do the logic of myClass version1 

} 

public void doMyClassLogicVersion2() { 

    Loader = // here i need to load jar2.myClass. 
    // myClass need a two params to initialize it in the normal case 
    // also i need to access its static members 
    // do the logic of myClass version2 
} 

так я могу это сделать, я знаю, что это не хорошо, но я на самом деле нужно.

ответ

2

Вы можете загрузить новый код в новый класс погрузчиков относительно легко:

Случай 1: Если ваши классы имеют общий родительский интерфейс (или класс) в текущем контексте, например, Runnable, вы можете использовать этот код:

public void doMyClassLogicVersion1() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL1 }, 
    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(); 
} 

public void doMyClassLogicVersion2() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL2 }, 
    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(); 
} 

Случай 2: Если классы не разделяют общий предок:

public void doMyClassLogicVersion1() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL1 }, 
    getClass().getClassLoader() 
    ); 
    Class<?> clazz = Class.forName("mypackage.MyClass", true, loader); 
    // Avoid Class.newInstance, for it is evil. 
    Constructor<?> ctor = runClass.getConstructor(); 
    Object obj = ctor.newInstance(); 

    String methodName = "getName"; 

    java.lang.reflect.Method method; 
    try { 
     method = clazz.getMethod(methodName, param1.class, param2.class, ..); 
    } catch (SecurityException e) { 
     // ... 
    } catch (NoSuchMethodException e) { 
     // ... 
    } 

    try { 
     method.invoke(obj, arg1, arg2,...); 
    } catch (IllegalArgumentException e) { 
     // ... 
    } catch (IllegalAccessException e) { 
     // ... 
    } catch (InvocationTargetException e) { 
     // ... 
    } 
} 

public void doMyClassLogicVersion2() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL2 }, 
    getClass().getClassLoader() 
    ); 
    Class<?> clazz = Class.forName("mypackage.MyClass", true, loader); 
    // Avoid Class.newInstance, for it is evil. 
    Constructor<?> ctor = runClass.getConstructor(); 
    Object obj = ctor.newInstance(); 

    String methodName = "getName"; 

    java.lang.reflect.Method method; 
    try { 
     method = clazz.getMethod(methodName, param1.class, param2.class, ..); 
    } catch (SecurityException e) { 
     // ... 
    } catch (NoSuchMethodException e) { 
     // ... 
    } 

    try { 
     method.invoke(obj, arg1, arg2,...); 
    } catch (IllegalArgumentException e) { 
     // ... 
    } catch (IllegalAccessException e) { 
     // ... 
    } catch (InvocationTargetException e) { 
     // ... 
    } 
} 
+0

ответа на удаляемый вопрос: почему URLClassLoader.newInstance? URLClassLoader.newInstance создает новый экземпляр URLClassLoader для указанных URL-адресов и загрузчика родительского класса по умолчанию. Если установлен диспетчер безопасности, метод loadClass для URLClassLoader, возвращаемый этим методом, вызывается SecurityManager.checkPackageAccess перед загрузкой класса. Источник: http://download.java.net/jdk8/docs/api/java/net/URLClassLoader.html#newInstance%28java.net.URL[]%29 –

+0

Спасибо mohammad, но мне все еще нужно ссылаться на конкретный метод содержит загруженный класс. так что придет с ур кодом. и есть два пата, которые содержат конструктор myClass. – Salah

+0

Имеют ли эти два класса один и тот же родительский класс? Если они есть, то вы можете заменить этот родительский класс Runnable в моем коде. –

0

Да, вы можете это сделать. Чтобы избежать проблем, я бы рекомендовал вам не помещать какие-либо из банок в обычный CLASSPATH, создавать 2 разных потока и устанавливать ContextClassLoader каждого потока в соответствующую банку перед их запуском.

Смежные вопросы