依赖于 dll 的可执行 Jar

Executable Jar with Dependency on dll

我正在尝试部署一个使用 dll 来促进数据库连接的 swing 应用程序(使用依赖于 sqljdbc_auth.dll 的 sqljdbc4 jar)。我的部署策略是创建一个可执行的 jar 文件。问题是我无法让依赖 sqljdbc_auth.dll 的函数在我创建的可执行 jar 中工作。

我可以使用以下任一方法使项目在 Eclipse 中正常运行:

  1. 通过在源文件夹中指定本机库位置,在构建路径配置中引用包含 dll 的文件夹
  2. 将dll放在C:\Windows\System32目录下
  3. 添加以下 VM 参数,引用我项目中 dll 文件夹的相对路径“-Djava.library.path=path/to/dllfolder”

我尝试过的第四种方法是通过以下行直接在代码中加载dll。 System.load("C:/Users/Me/Desktop/sqljdbc_auth.dll"); 我用这种方法没有成功,并收到以下错误。

Mar 20, 2015 4:18:44 PM com.microsoft.sqlserver.jdbc.AuthenticationJNI <clinit> WARNING: Failed to load the sqljdbc_auth.dll cause : no sqljdbc_auth in java.library.path

但是,该错误并非直接来自加载库的代码行,它似乎是在 sqljdbc 库尝试加载用于建立连接的 dll 时出现的。

无论哪种方式,当我通过 eclipse 的导出功能将应用程序部署为可执行 jar 文件时,我都无法使用上述任何方法。我唯一能得到的就是前面提到的错误信息。

以下示例应用程序产生相同的结果。

public class TestApp {
public static void main(String[] args){

        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                JFrame mainFrame = new JFrame();
                mainFrame.setSize(300,300);
                mainFrame.setLocationRelativeTo(null);
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                mainFrame.setVisible(true);

            try{
                //System.load("C:/Users/Me/Desktop/sqljdbc_auth.dll");
                String serverName = "local";
                String databaseName = "test_database";
                String connString = "jdbc:sqlserver://" + serverName + "; databaseName=" + databaseName + ";integratedSecurity=true";

                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
                Connection  conn = DriverManager.getConnection(connString);
                Statement st = conn.createStatement();
                ResultSet rs = st.executeQuery("select distinct name from test_table");
                rs.next();

                JOptionPane.showMessageDialog(null, "From db: " + rs.getString(1), "Test", JOptionPane.INFORMATION_MESSAGE);

            } catch (SQLException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, e.getMessage(), "Test", JOptionPane.INFORMATION_MESSAGE);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, e.getMessage(), "Test", JOptionPane.INFORMATION_MESSAGE);
            } catch (Exception e){
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, e.getMessage(), "Test", JOptionPane.INFORMATION_MESSAGE);
            }
        }
    });     
}

}

我已经阅读了大量关于将 dll 与可执行 jar 一起使用的帖子,它们似乎都提到了使用这种 System.load 方法。具有讽刺意味的是,这是我无法工作的一件事。我知道我有正确的 dll;但是,因为我可以获得其他方法在 IDE 环境中工作。我不在乎dll是否与可执行jar一起打包,我只希望它能工作!

我认为这与将 dll 放入您的库有关

(In Eclipse, Properties->Java Build Path->Libraries).

导出 jar 时,您还可以选择将库文件导出到文件夹中。

如果你在那之后反编译 Jar,你会注意到有一个清单文件,里面有你的库文件所在的路径(基于导出,它为你创建了一个库文件夹,通常 jarname_lib).

导出时,您可以选择另存为 ANT 文件,然后您可以编辑该文件以将库文件的导出位置更改为您选择的文件夹名称。然后,您可以将这个编辑过的 ANT 文件添加到您的构建中,以便在您构建项目时它会发生:

(In Eclipse, Properties->Builders->New)