Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Two jars in project with same class.

I have a java project that is using two imported jars with the same class (com.sun.mail.imap.IMAPFolder). Is there a way to explicitly say which jar to use when importing the class? Using:

import com.sun.mail.imap.IMAPFolder; 

would seem to use the class in order of build path order but this does not seem to be the case for some reason causing

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.NoSuchMethodError: com.sun.mail.imap.IMAPFolder.idle()V
        at com.woodbury.GCM.HelperGmailMonitor.doEmail(HelperGmailMonitor.java:104)
        at com.woodbury.GCM.Launch.listen(Launch.java:16)
        at com.woodbury.GCM.Launch.main(Launch.java:10)
        ... 5 more

at runtime. I am building the project in eclipse.

like image 278
Fenrir Avatar asked Oct 12 '13 22:10

Fenrir


People also ask

How do I compare two Java JARs?

Depending on your system settings, you should be able to just double click the jar file to run it, or right-click and select to run it. Then the tool will prompt for the two files to compare.

Can two classes have same name in Java?

Note that you can't import two classes with the same name in two different packages. The classes Integer and String belongs to the package java. lang but they don't need to be imported as the java.

How do I run a specific class in a jar?

To run an application in a nonexecutable JAR file, we have to use -cp option instead of -jar. We'll use the -cp option (short for classpath) to specify the JAR file that contains the class file we want to execute: java -cp jar-file-name main-class-name [args …]


1 Answers

When a class is loaded, the first implementation that matches the requested fully qualified name that is visible to the relevant ClassLoader is what gets returned. Any other implementations with the same fully qualified name are effectively hidden to that ClassLoader.

What this means in a standard Java SE application is that the first code base (i.e. a jar) listed on the classpath with the required class, provides it, and all other code bases' implementations of the same fully qualified class are hidden.

Example:

Assume that A.jar contains the compiled class

package com.stackoverflow.example;
public class Hello {
     public static String getGreeting(){
         return "Hello, A!"
     }
}

Assume that B.jar contains the compiled class

package com.stackoverflow.example
public class Hello {
     public static String getGreeting(){
         return "Hello, B!"
     }
}

Note that in both of the above classes have the same fully qualified name.

Assume main class is

   import com.stackoverflow.example.Hello;

   public class ExampleMain {
       public static void main(String[] args){
            System.out.println(Hello.getGreeting());
       }
   }

If I were to invoke my program with

java -cp A.jar:B.jar ExampleMain

the output is: Hello, A!

If I reverse the classpath like so

java -cp B.jar:A.jar ExampleMain

the output is: Hello, B!

like image 73
Dev Avatar answered Oct 02 '22 15:10

Dev