1

I'm trying to load dynamically a class contained in a .jar file. I know the whole class name and I know for sure that the class implements the interface AlgorithmClass. My code looks like this:

addURLToSystemClassLoader(dir.toURI().toURL());
Class cl = Class.forName(algorithm.getClassName());
AlgorithmClass algorithmClass = (AlgorithmClass)cl.newInstance();

Where dir is the File object of the .jar file and addURLToSystemClassLoader(URL) looks like this:

private void addURLToSystemClassLoader(URL url) throws IntrospectionException {
        URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        Class<URLClassLoader> classLoaderClass = URLClassLoader.class; 
        try {
            Method method = classLoaderClass.getDeclaredMethod("addURL", new Class[]{URL.class});
            method.setAccessible(true);
            method.invoke(systemClassLoader, new Object[]{url});
        } catch (Throwable t) {
            t.printStackTrace();
            throw new IntrospectionException("Error when adding url to system ClassLoader ");
        }
    }

I checked and the URL is being added to the class loader.

When I try to get the Class object I get the error:

SEVERE: javax.servlet.ServletException: java.lang.ClassNotFoundException: id3.Algorithm

(id3.Algorithm is the full name of the class I'm trying to load)

I've tried creating a new ClassLoader like below:

ClassLoader cload = new URLClassLoader(new URL[]{dir.toURI().toURL()}, ClassLoader.getSystemClassLoader());
Class cl = Class.forName(algorithm.getClassName(), false, cload);
AlgorithmClass algorithmClass = (AlgorithmClass)cl.newInstance();

But then I get the error:

java.lang.NoClassDefFoundError: lib/algorithm/AlgorithmClass

I've tried creating a new URLClassLoader with all the URLs that the system class loader has but the effect was the same.

The "worst" part of this is that both ways are working perfectly fine on the jUnit test that I have for testing this part of my code.

I'm using Glassfish 3.1.1 as my app server.

4
  • make sure that the jar is being loaded before than this code execution Commented May 7, 2012 at 17:44
  • @Luiggi Mendoza What do you mean? The whole point of this code is to dynamically load the class in that part of the code. Commented May 7, 2012 at 18:00
  • I mean you should make sure that when the Application Server will deploy your application it can find the jars (including the one that contains ide.*) and all of them are deployed before your war code is compiled. Commented May 7, 2012 at 18:03
  • @LuiggiMendoza not really because the .jar that I'm using here is beeing uploaded after the deploy. Commented May 7, 2012 at 18:39

2 Answers 2

1

dir shouldn't contain 'lib'. Try this:

 ClassLoader cload = new URLClassLoader(new URL[]{dir.toURI().toURL()}, Thread.currentThread().getContextClassLoader());
 Class cl = Class.forName(algorithm.getClassName(), true, cload);
 AlgorithmClass algorithmClass = (AlgorithmClass)cl.newInstance();
Sign up to request clarification or add additional context in comments.

Comments

0

You have class-loading issue. You shoud be aware that your addURLToSystemClassLoader() is actually the heck...

Put your jar to the classpath. Use Class.forName() idiom. If it fails use version that receives ClassLoader as parammeter namely

   public static Class<?> forName(String name, boolean initialize,
                               ClassLoader loader)

and path Thread.currentThread().getContextClassLoader() as ClassLoader parameter.

See also my another answer below.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.