简体   繁体   English

URLClassLoader无法读取插件的外部JAR库

[英]URLClassLoader does not read external JAR library of a plugin

I have implemented a simple plugin based application with Java. 我已经用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. 应用程序从JAR文件中读取该类,并通过创建该类的实例来运行插件。 Standard procedure I guess :) 我猜标准程序:)

Everything forks fine until now. 到目前为止一切都很好。 But the problem occurs when I include a library to my plugin, like MySQL Connector. 但是,当我在插件中包含一个库(例如MySQL Connector)时,就会出现问题。 The exception NoClassDefFoundError and ClassNotFoundException are thrown after execution. 执行后引发NoClassDefFoundError和ClassNotFoundException异常。 I am overcoming the problem by adding MySQL connector library to the main application but what is the point then? 我通过将MySQL连接器库添加到主应用程序中来克服此问题,那又有什么意义呢? :) :)

I am not a Java expert so I am not sure of any alternative solutions like defining a classpath for libraries etc. 我不是Java专家,所以我不确定是否有其他替代解决方案,例如为库定义类路径等。

Here is my plugin loader: http://pastebin.com/90rQ9NfJ 这是我的插件加载器: http : //pastebin.com/90rQ9NfJ

And here is my plugin base class: http://pastebin.com/Juuicwkm 这是我的插件基类: http : //pastebin.com/Juuicwkm

I am executing from a GUI: 我正在从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? 您如何通过命令行或GUI执行类? If from the command line, then the MySQLConnector libraries, along with any other dependent library must be included in the classpath (java -classpath). 如果从命令行,则MySQLConnector库以及任何其他依赖库必须包含在类路径中(java -classpath)。 The top answer to this question should help you- Java: how to import a jar file from command line 这个问题的最佳答案应该对您有帮助-Java:如何从命令行导入jar文件

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. 如果是这样,您的类是Mysql驱动程序,则必须排除(在类调用时)不可用的类。 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. 在您的.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", ""));
                 }
                }
}

This should load a mysql.xxx.jar file. 这应该加载一个mysql.xxx.jar文件。 Try This 尝试这个


dynamicload.java 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 ??? 好 ???

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM