4

I´m trying to load a class from a jar, I´m using a classLoader.

I have this parts of code for prepare the classLoader:

private void loadClass(){

    try{
        JarFile jarFile = new JarFile( Path);
        Enumeration e = jarFile.entries();

        URL[] urls = { new URL("jar:file:" + Path +"!/") };
        classLoader = URLClassLoader.newInstance(urls);


    } catch (MalformedURLException ex) {
        // TODO Auto-generated catch block
        ex.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

Now I load a class, and I try to get a new instance

....           
           loadClass();

           Class device = classLoader.loadClass( "org.myPackage.MyClass");

           MyMotherClass Device = ( MyMotherClass) device.newInstance();
...

MyClass extends of MyMotherClass, and when I do classLoader.loadClass( "org.myPackage.MyClass"), the MyMotherClass it is in the classLoader. At the moment, all right.

now, in device.newInstance(), I get a exception. The problem is the other classes that are used by MyClass, are not in the classpath.

What can i do?

I have a another method that load all the needed classes in the classLoader, but does not work when I get the new instance. I can not change MyClass and the others

Clonw
  • 75
  • 6
  • Can you not change your classpath settings in advance of starting the JVM? – Bathsheba Dec 12 '13 at 16:57
  • 1
    Does this help you out? http://stackoverflow.com/questions/402330/is-it-possible-to-add-to-classpath-dynamically-in-java – Andrew Wells Dec 12 '13 at 16:59
  • @Bathsheba No, I do not know the jar has to be loaded. The name it is create in runtime – Clonw Dec 12 '13 at 17:00
  • Can you be more specific about "the other classes that are used by MyClass"? Also, is the classloader you're loading `MyClass` with different than the system classloader? – Floegipoky Dec 12 '13 at 17:03
  • I have a lot of jars, one of a each device and I need to load only one jar. – Clonw Dec 12 '13 at 17:04
  • 1
    That makes sense but doesn't answer either of my questions, which makes it difficult to help. Taking a shot in the dark, it sounds like you're loading MyClass with a classloader that doesn't delegate back to the system classloader. If this isn't the case, then the missing classes aren't being loaded correctly. – Floegipoky Dec 12 '13 at 17:19
  • Give the public static method from `java.lang.Class` a try: `Class.forName(String, boolean, ClassLoader)`. MyMotherClass Device = ( MyMotherClass) java.lang.Class.forName("org.myPackage.MyClass", true, classLoader). It shouldn't make much of a difference but just try it as a long-shot possible solution. – initramfs Dec 12 '13 at 17:25

1 Answers1

2

Here's some code I use to load a jar dynamically at run-time. I exploit reflection to circumvent the fact that you ain't really supposed to do this (that is, modify the class path after the JVM has started). Just change my.proprietary.exception to something sensible.

    /*
     * Adds the supplied library to java.class.path.
     * This is benign if the library is already loaded.
     */
    public static synchronized void loadLibrary(java.io.File jar) throws my.proprietary.exception
    {
        try {
            /*We are using reflection here to circumvent encapsulation; addURL is not public*/
            java.net.URLClassLoader loader = (java.net.URLClassLoader)ClassLoader.getSystemClassLoader();
            java.net.URL url = jar.toURI().toURL();
            /*Disallow if already loaded*/
            for (java.net.URL it : java.util.Arrays.asList(loader.getURLs())){
                if (it.equals(url)){
                    return;
                }
            }
            java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
            method.setAccessible(true); /*promote the method to public access*/
            method.invoke(loader, new Object[]{url});
        } catch (final NoSuchMethodException | 
            java.lang.IllegalAccessException | 
            java.net.MalformedURLException | 
            java.lang.reflect.InvocationTargetException e){
            throw new my.proprietary.exception(e.getMessage());
        }
    }
Bathsheba
  • 231,907
  • 34
  • 361
  • 483