【问题标题】:Calling same Method having same packageName From Different JARs [duplicate]从不同的 JAR 调用具有相同 packageName 的相同方法 [重复]
【发布时间】:2013-11-04 13:26:53
【问题描述】:

我有三个 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");

        }

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

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

【问题讨论】:

    标签: java jar classloader


    【解决方案1】:

    也许你的 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 中添加此接口!

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2020-03-20
        • 2014-08-31
        • 2012-08-11
        • 2011-11-24
        • 2013-10-15
        • 2011-12-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多