简体   繁体   中英

Load a class from a jar having dependency on another jar

My project structure is the following (very simplified of course): 项目结构

So under lib-ext i download on a daily basis from a Jenkins server 2 jar files 'jar1 and jar2' to be checked by my program, i need one file from 'jar1' lets call it: "Class2Bloaded". The issue is that this file implements an interface that is to be found in 'jar2', lets call this 'Dependency'

What i would like to do is, from my class under src "ClassThatLoads.java", load 'Class2Bloaded.class' and tell the class loader to look into 'jar2' to search for the implementing interface "Dependency.class"

My code so far (omitting exceptions handling):

    //Create the URL pointing to Jar1
  private URL getJarUrl(JarFile jarFile)
  {
      return new File(jarFile.getName()).toURI().toURL();
  }

  URL jar1Url = getJarUrl(jar1);
  ClassLoader jar1classLoader = new URLClassLoader(new URL[] { jar1Url });
  Class<?> Class2Bloaded = Class.forName(fullClassName, false, jar1classLoader );

So the problem happens within the Class.forName invocation, because the class i want to load implements an interface that is in jar 2.

Exception in thread "main" java.lang.NoClassDefFoundError: com/packagewithinJar2/Dependency

So eventually i have prepared another class loader that points to 'jar2', and i have even got the actual Interface i need:

URL jar2Url = getJarUrl(jar2);
  ClassLoader jar2classLoader = new URLClassLoader(new URL[] { jar2Url });
  Class<?> Interface2Bloaded = Class.forName(fullClassName, false, jar2classLoader );

Where 'fullClassName' in the second case is the fully qualified name of the interface from which 'Class2Bloaded' depends on. Is just that i cant find anything in the javadocs of ClassLoader that allows me to 'inject' an additional class loader for the dependencies. I hope my explanation is clear.

The first thing to do would be to add jar2 to the list of jars your URLClassLoader reads:

ClassLoader jarclassLoader = new URLClassLoader(new URL[] { jar1Url, jar2Url });

BUT the normal thing to do would be to add jar1 and jar2 on your classpath from the beginning.

To do so you would use the -cp parameter of the java executable.

for example, if you compile your classes into the bin directory:

java -cp libext/jar1.jar:libext/jar2.jar:bin ClassThatLoads

That way, you could use the classes seamless in your own java source and get rid of the cumbersome loading part :

public class ClassThatLoads {
  public static void main(String[] args) {
    Class2Bloaded stuff = new Class2Bloaded();
    //use stuff from here...
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM