1

我有三个 Jar 文件。所有 jar 文件都包含相同的类 TestServicesImpl 和相同的方法 displayWeLcomeMessage() 但具有不同的 displayWeLcomeMessage() 消息(输出)。 例子 :

public void displayWeLcomeMessage() {
        System.out.println("wecome msg of JAR version first");

    }

 public void displayWeLcomeMessage() {
            System.out.println("wecome msg of JAR version two");

        }

 public void displayWeLcomeMessage() {
            System.out.println("wecome msg of JAR version third");

        }

我有一个主要应用程序,它包含包含的罐子。我的主应用程序调用 displayWeLcomeMessage() 方法。

第一个 JAR 被添加到类路径中,第二个 JAR 使用自定义类加载器和调用方法 displayWeLcomeMessage() 加载。

    File file  = new File("C:/Users/amitk/Desktop/Test_1.0.2.jar");
    @SuppressWarnings("deprecation")
    URL url = file.toURL();  
    URL[] urls = new URL[]{url};
    URLClassLoader  loader = new URLClassLoader(urls);

    Class classS = loader.loadClass("com.amit.servicesImpl.TestServicesImpl");
    Object object = classS.newInstance();
    Method getmsg = classS.getMethod("displayWeLcomeMessage");
     getmsg.invoke(object);

但它首先显示与 JAR 方法相同的消息。在我的第三个 JAR 中,我更改了包名。即 com.amit.servicesImpl.TestServicesImpl更改为com.amit.servicesImpl2.TestServicesImpl 并且这次它可以正常工作,即此处显示 JAR 3 方法的消息。

所以让我知道这背后的主要问题和解决方案。

4

2 回答 2

2

也许您的初始类加载器中有您的 JAR。URLClassLoader 将在检查自己的空间之前检查父类加载器中的现有类。

1)您可以扩展和修改此行为:

package com.mytool;

import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
import java.util.HashMap;
import java.util.Map;

public class MyURLClassLoader extends URLClassLoader {

    private final Map<String, Class<?>> ourClasses = new HashMap<>();

    public MyURLClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    public MyURLClassLoader(URL[] urls) {
        super(urls);
    }

    public MyURLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
        super(urls, parent, factory);
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = ourClasses.get(name);

            if (c == null) {
                // search in our paths
                try {
                    c = findClass(name);
                    ourClasses.put(name, c);
                } catch (ClassNotFoundException e) {
                    // ignore
                }
            }

            if (c == null) {
                c = findLoadedClass(name);
            }

            if (c != null) {
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }

            // default search
            return super.loadClass(name, resolve);
        }
    }
}

2) 或者您可以尝试移动我们的 JAR,而不是在 JVM 启动时加载它。

注意: 我将使用仅由初始类加载器加载的接口,而不是使用完全自反性。您的对象可以实现它,并且您将能够转换到此接口。如果您使用 MyURLClassLoader 执行此操作,请不要在我们动态加载的 JAR 中添加此接口!

于 2013-10-25T12:42:42.610 回答
0

类加载器将选择首先找到的类。如果您有 10 个具有相同类的包,则只会选择首先引入的类。

于 2013-10-25T12:50:05.010 回答