Pregunta

I am trying to add JAR file to class path and load all classes from JAR file at run time. here is the code I wrote for this task (This class extends URLClassLoader)

public void loadJar(final String fName) throws IOException, IllegalAccessException, ClassNotFoundException {
    final File file = new File(fName);
    if (file.exists() && getFileExtension(file.getName()).equalsIgnoreCase("jar")) {
        addURL(file.toURI().toURL());
        for(final URL url : getURLs()){
            System.out.println(url.toString());
        }
        final ZipFile jarFile = new ZipFile(file, ZipFile.OPEN_READ);
        final Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) jarFile.entries();
        while (entries.hasMoreElements()) {
            final String className = getClassCanonicalName(entries.nextElement());
            if (className != null) {
                loadClass(getClassCanonicalName(entries.nextElement()));
            }
        }
    }
}

private String getFileExtension(final String fileName) {
    return fileName.substring(fileName.lastIndexOf(".") + 1);
}

private String getClassCanonicalName(final ZipEntry entry) {
    final String entryName = entry.getName();
    if (getFileExtension(entryName).toLowerCase().endsWith("class")) {
        return entryName.replaceAll(File.separator, ".");
    } else {
        return null;
    }
}

But I keep getting ClassNotFoundException for class entities even through getURLs does indicate jar files has been added to this loader.

What is the cause of this problem? Thanks

¿Fue útil?

Solución

return entryName.replaceAll(File.separator, "."); 

On Windows this will fail. It should be / for the separator of a ZipEntry for a Zip made on any platform.

So replace that with:

return entryName.replaceAll("/", "."); 

Also strip the class name. SSCCE E.G.:

import java.io.*;
import java.net.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class URLClassLoaderTest extends URLClassLoader {

    public URLClassLoaderTest(URL[] arg0) {
        super(arg0);
    }

    public void loadJar(URL urlOfJar) throws IOException, IllegalAccessException, ClassNotFoundException {
        if (getFileExtension(urlOfJar.getFile()).equalsIgnoreCase("jar")) {
            addURL(urlOfJar);
            for(final URL url : getURLs()){
                System.out.println(url.toString());
            }
            final ZipInputStream zis = new ZipInputStream(urlOfJar.openStream());
            ZipEntry ze = zis.getNextEntry();
            while (ze!=null) {
                final String className = getClassCanonicalName(ze);
                if (className != null) {
                    loadClass(getClassCanonicalName(ze));
                }
                ze = zis.getNextEntry();
            }
        }
    }

    private String getFileExtension(final String fileName) {
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    private String getClassCanonicalName(final ZipEntry entry) {
        final String entryName = entry.getName();
        if (getFileExtension(entryName).toLowerCase().endsWith("class")) {
            String s = entryName.substring(0,entryName.length()-6);
            s = s.replaceAll("/", ".");
            System.out.println(s);
            return s;
        } else {
            return null;
        }
    }

    public static void main(String[] args) throws Exception {
        URL[] url = {new URL("http://pscode.org/lib/mime.jar")};
        URLClassLoaderTest uclt = new URLClassLoaderTest(url);
        uclt.loadJar(url[0]);
    }
}

Output

http://pscode.org/lib/mime.jar
org.pscode.mime.MimeType$1
org.pscode.mime.MimeType$1
org.pscode.mime.MimeType$2
org.pscode.mime.MimeType$2
org.pscode.mime.MimeType
org.pscode.mime.MimeType
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top