Исполняемый Jar с зависимостью от dll

Я пытаюсь развернуть приложение Swing, которое использует dll для облегчения подключения к базе данных (используя jar sqljdbc4, который зависит от sqljdbc_auth.dll). Моя стратегия развертывания заключается в создании исполняемого файла jar. Проблема в том, что я не могу заставить функции, которые полагаются на sqljdbc_auth.dll, работать в исполняемом банке, который я создаю.

Я могу заставить проект работать нормально в eclipse, используя любой из следующих методов:

  1. Ссылка на папку, содержащую dll, в конфигурации пути сборки, указав расположение собственной библиотеки в исходной папке.
  2. Поместите dll в каталог C:\Windows\System32
  3. Добавьте следующий аргумент виртуальной машины, ссылающийся на относительный путь к папке 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 для использования при установлении соединения.

В любом случае, я не могу заставить что-либо из вышеперечисленных методов работать, когда я развертываю приложение в виде исполняемого файла jar с помощью функции экспорта eclipse. Единственное, что я могу получить, это ранее упомянутое сообщение об ошибке.

Следующий пример приложения дает тот же результат.

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 или нет, я просто хочу, чтобы она работала!


person CurtisF    schedule 20.03.2015    source источник


Ответы (1)


Я бы предположил, что это как-то связано с помещением dll в вашу библиотеку.

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

Когда вы экспортируете банку, у вас также будет возможность экспортировать файлы библиотеки в папку.

Если вы после этого декомпилируете Jar, вы заметите, что есть файл манифеста и в нем пути к файлам вашей библиотеки (на основе экспорта, который создал для вас папку библиотеки, обычно jarname_lib).

При экспорте у вас есть возможность сохранить как файл ANT, который затем можно отредактировать, чтобы изменить местоположение экспорта файлов библиотеки на имя папки по вашему выбору. Затем вы можете добавить этот отредактированный файл ANT в свою сборку, чтобы это происходило всякий раз, когда вы собираете проект:

(In Eclipse, Properties->Builders->New)
person space_food_    schedule 20.03.2015
comment
Спасибо за совет. Я добавил расположение папки dll (пробовал как внешнюю папку, так и папку в проекте) в качестве расположения собственной библиотеки в пути сборки Java (это единственный способ понять, как это сделать, не получая ошибок сборки). Это отлично работает в eclipse, но все равно не работает, когда я экспортирую проект. Я также сохранил файл ANT, но он экспортировал только библиотеки jar, а не dll. Поэтому я понятия не имею, куда поместить dll или как попытаться указать их местоположение. - person CurtisF; 23.03.2015
comment
Я бы предположил, что в файле ANT внутри тега <manifest> библиотеки dll должны находиться в пути к классам, как и банки. Итак, вот так: <attribute name="Class-Path" value=". my_lib/somejar.jar my_lib/somedll.dll"/>. В этом случае, если бы основной jar находился в C:/, файлы библиотеки экспортировались бы в C:/my_lib Что касается экспорта dll и jar, это выглядело бы так <delete dir="C:/my_lib"/> <mkdir dir="C:/my_lib"/> <copy file="C:/whatever/somejar.jar" todir="C:/my_lib"/> - person space_food_; 24.03.2015
comment
Получил это работает. Настройка манифеста позволила мне переместить некоторые переключатели, которые я не мог раньше. В качестве справки для других, у кого могут возникнуть проблемы, я обнаружил, что если вы не хотите возиться с манифестом, вы также можете поместить dll в папку bin установки java, поскольку это расположение библиотеки по умолчанию. - person CurtisF; 24.03.2015
comment
Можете ли вы объяснить, как вы это сделали? - person sh4r4d; 24.09.2020