从不同的JAR调用具有相同packageName的相同方法

时间:2013-10-25 12:16:04

标签: java jar classloader

我有三个Jar文件。所有jar文件都包含Same class TestServicesImpl和Same Method 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");

        }

我有一个主要应用程序,它包含包含的jar。我的主应用程序调用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方法的消息。

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

2 个答案:

答案 0 :(得分: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中添加此接口!

答案 1 :(得分:0)

Classloader将选择首先找到的类。如果你有10个具有相同类的包,那么只会选择首先引入的类。