【问题标题】:URLClassLoader does not read external JAR library of a pluginURLClassLoader 不读取插件的外部 JAR 库
【发布时间】:2012-04-27 23:35:45
【问题描述】:

我已经用 Java 实现了一个简单的基于插件的应用程序。主插件类派生自称为“插件”的抽象类。应用程序从 JAR 文件中读取该类并通过创建该类的实例来运行插件。我猜是标准程序:)

到目前为止一切正常。但是当我在我的插件中包含一个库时会出现问题,比如 MySQL 连接器。执行后抛出异常 NoClassDefFoundError 和 ClassNotFoundException。我通过将 MySQL 连接器库添加到主应用程序来克服这个问题,但那有什么意义呢? :)

我不是 Java 专家,因此我不确定是否有任何替代解决方案,例如为库定义类路径等。

这是我的插件加载器: http://pastebin.com/90rQ9NfJ

这是我的插件基类: http://pastebin.com/Juuicwkm

我正在从 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));
        }
    }

【问题讨论】:

    标签: java plugins jar classloader urlclassloader


    【解决方案1】:

    你真的应该包括你的源代码。

    您是如何执行该类的,即通过命令行还是从 GUI?如果从命令行,则 MySQLConnector 库以及任何其他依赖库必须包含在类路径中 (java -classpath)。这个问题的最佳答案应该对您有所帮助-Java: how to import a jar file from command line

    【讨论】:

    【解决方案2】:

    如果是这种情况,您的类是 Mysql 驱动程序,您必须排除(在类调用时)不可用的类。在 .jar 文件的文件夹中,有一个名为“integration”的文件夹,其中包含“jboss”和“c3p0”,目前不存在。

    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", ""));
                     }
                    }
    }
    

    这应该加载一个 mysql.xxx.jar 文件。 试试这个


    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("-----------------------------------------------");
        }
    }
    

    输出:

    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
    -----------------------------------------------
    

    好的???

    【讨论】:

    • 不幸的是,JAR 结构中没有这样的“集成”文件夹。
    • 我在“mysql-connector-java-5.0.4-bin.jar”和“mysql-connector-java-5.1.6-bin.jar”中找到了id。请告诉我你的 .jar 文件的名称。
    • 并且在刚刚下载的MySql download
    • 我正在使用“mysql-connector-java-5.1.19-bin.jar”
    • 我在上面添加了代码。更改设置并运行。有一个“com/mysql/jdbc/integration/”文件夹。你可以相信我;)
    猜你喜欢
    • 2017-11-14
    • 2016-11-29
    • 2015-06-30
    • 1970-01-01
    • 2012-10-28
    • 2012-01-13
    • 2013-12-08
    • 1970-01-01
    相关资源
    最近更新 更多