0

我有一个新的小 Swing 项目,我需要从两个不同的 jarsm 加载相同的类,这些 jars 是第三方,所以我没有源代码。

例如,我需要从两个 jar 中加载 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
}

所以我可以这样做,我知道这对这不好,但我真的需要。

4

2 回答 2

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) {
      // ...
    }
}
于 2013-08-22T20:16:26.733 回答
0

是的,你可以做到。为避免出现问题,我建议您不要将任何 jar 放在常规 CLASSPATH 中,创建 2 个不同的线程,并在启动它们之前将每个线程的 ContextClassLoader 设置为相应的 jar。

于 2013-08-22T20:12:15.313 回答