简体   繁体   中英

URLClassLoader does not read external JAR library of a plugin

I have implemented a simple plugin based application with Java. Main plugin class is derived from and abstract class called "Plugin". The application reads that class from JAR file and runs the plugin by creating an instance of the class. Standard procedure I guess :)

Everything forks fine until now. But the problem occurs when I include a library to my plugin, like MySQL Connector. The exception NoClassDefFoundError and ClassNotFoundException are thrown after execution. I am overcoming the problem by adding MySQL connector library to the main application but what is the point then? :)

I am not a Java expert so I am not sure of any alternative solutions like defining a classpath for libraries etc.

Here is my plugin loader: http://pastebin.com/90rQ9NfJ

And here is my plugin base class: http://pastebin.com/Juuicwkm

I am executing from a GUI:

    private void jButtonAddActionPerformed(java.awt.event.ActionEvent evt) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new FileNameExtensionFilter("JTask Plugin (*.JAR)", "JAR"));

        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
        {
            File pluginFile = fileChooser.getSelectedFile();
            PluginLoader pluginLoader = new PluginLoader();
            Plugin plugin = pluginLoader.loadPlugin(pluginFile);
            if (plugin != null)
                jPanelPlugins.add(new PluginControl(jPanelPlugins, plugin));
        }
    }

You should really include your source code as well.

How are you executing the class ie via command line or from a GUI? If from the command line, then the MySQLConnector libraries, along with any other dependent library must be included in the classpath (java -classpath). The top answer to this question should help you- Java: how to import a jar file from command line

if the case, your class is a Mysql Driver you have to exclude (at the time the class is calling) classes that are not available. In the Folder of your .jar file there is one with the name "integration" it contains "jboss" and "c3p0" which are not present at this time.

while (en.hasMoreElements()) { 
                JarEntry entry = new JarEntry(en.nextElement());
                String name = entry.getName();
                if (name.contains("/integration/")) {
                  continue;
                } else {
                 if (!entry.isDirectory() && name.toLowerCase().endsWith(".class"))
                 {
                    classList.add(name.replace(".class", ""));
                 }
                }
}

This should load a mysql.xxx.jar file. Try This


dynamicload.java


package dynamicloading;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 *
 * @author Administrator
 */
class com_mysql_jdbc_Driver implements Driver {
    private Driver driver;
    com_mysql_jdbc_Driver(Driver cmjd) {
        this.driver = cmjd;
    }
    @Override
    public boolean acceptsURL(String aurlS) throws SQLException {
        return this.driver.acceptsURL(aurlS);
    }
    @Override
    public Connection connect(String aurlS, Properties pP) throws SQLException {
        return this.driver.connect(aurlS, pP);
    }
    @Override
    public int getMajorVersion() {
        return this.driver.getMajorVersion();
    }
    @Override
    public int getMinorVersion() {
        return this.driver.getMinorVersion();
    }
    @Override
    public DriverPropertyInfo[] getPropertyInfo(String aurlS, Properties pP) throws SQLException {
        return this.driver.getPropertyInfo(aurlS, pP);
    }
    @Override
    public boolean jdbcCompliant() {
        return this.driver.jdbcCompliant();
    }
}

public class DynMain {

    /**
     * @param args the command line arguments
     */

    public static void main(String[] args) throws Exception {
        /* please set to your path*/
        File file = new File("U:/mozsamples/mysql-connector-java-5.1.19-bin.jar");
        Driver cmjdD;
        String aktCS;
        String urlS = "jdbc:mysql://localhost/db";
        String userS = "must-be-set";
        String passS = "must-be-set";
        Connection con;
        Statement stmt;
        URLClassLoader clazzLoader = URLClassLoader.newInstance(new URL[]{file.toURI().toURL()});
        JarFile jarFile = new JarFile(file);
        Enumeration<JarEntry> entries = jarFile.entries();

        while (entries.hasMoreElements()) {
            JarEntry element = entries.nextElement();
            if (element.getName().endsWith(".class")) {
                String name = element.getName();
                if (name.contains("/integration/")) {
                  System.out.println( "ignored: " + name );
                  continue;
                } else
                {
                try {    
                    aktCS = element.getName().replaceAll(".class", "").replaceAll("/", ".");
                    clazzLoader.loadClass(aktCS);
                    if (name.contains("com/mysql/jdbc/Driver")) {
                        cmjdD = (Driver)Class.forName(aktCS, true, clazzLoader).newInstance();
                        try {
                        DriverManager.registerDriver(new com_mysql_jdbc_Driver(cmjdD));
                        System.out.println( "register Class: " + aktCS );
                        } catch (SQLException e) {
                          e.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                }
            }
        } 
    try {
    con = DriverManager.getConnection(urlS,userS,passS);
    stmt = con.createStatement();
    /*ResultSet rs = stmt.executeQuery("select * from idcart where ID=255"); */

    stmt.close();
    } catch (SQLException esql) {
        esql.printStackTrace();
    }
   int j=0 ;
   System.out.println("loaded Driver----------------------------------");
   for( Enumeration en = DriverManager.getDrivers() ; en.hasMoreElements() ; j++)
         System.out.println( en.nextElement().getClass().getName() );

   if (j==0) { System.out.println("Driverlist empty"); }

    System.out.println("-----------------------------------------------");
    }
}

Output:

register Class: com.mysql.jdbc.Driver
ignored: com/mysql/jdbc/integration/c3p0/MysqlConnectionTester.class
ignored: com/mysql/jdbc/integration/jboss/ExtendedMysqlExceptionSorter.class
ignored: com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.class
loaded Driver----------------------------------
sun.jdbc.odbc.JdbcOdbcDriver
dynamicloading.com_mysql_jdbc_Driver
-----------------------------------------------

OK ???

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