2015-07-20 27 views
0

我正在維護需要連接到Microsoft SQL Server實例的Java Swing應用程序。出於各種原因,我選擇替換與jTDS一起使用的本機SQL Server驅動程序(前面提到的微軟驅動程序當時不工作,並且在該領域顯然也失敗了)。當我嘗試在IDE外運行可執行文件.jar時,我遇到了問題,因爲我缺少相應的ntlmauth.dll依賴項。手動加載本機庫以繞過限制性環境

開始之前,一定要注意,這個應用程序被開發並在一個非常嚴格的(僅Windows)環境中使用是很重要的:

  • 我不能安裝任何軟件需要Windows UAC認證
  • 我用戶無法安裝或運行任何需要UAC身份驗證的軟件
  • 這意味着我無法將文件寫入System32或JAVA_HOME,也無法使用任何類型的ProcessBuilder tomfoolery來啓動另一個JVM,並使用我需要的任何命令行參數
  • 我不能使用可執行包裝/安裝,將只需要在第一次安裝的UAC權限/設置

我試圖解決方案是this onethis one to check it --essentially包裝內該.dll組合.jar,然後解壓縮並在必要時加載 - 因爲我發現的大多數其他解決方案都與上述限制不兼容;然而,即使在本地庫被表面上「加載」之後,我遇到了一個問題,但我得到了一個異常,說它不是。

我的預啓動代碼:

private static final String LIB_BIN = "/lib-bin/"; 
private static final String JTDS_AUTH = "ntlmauth"; 

// load required JTDS binaries 
static { 
    logger.info("Attempting to load library {}.dll", JTDS_AUTH); 
    try { 
     System.loadLibrary(JTDS_AUTH); 
    } catch (UnsatisfiedLinkError e) { 
     loadFromJar(); 
    } 

    try { 
     // do some quick checks to make sure that went ok 
     NativeLibraries nl = new NativeLibraries(); 
     logger.debug("Loaded libraries: {}", nl.getLoadedLibraries().toString()); 
    } catch (NoSuchFieldException ex) { 
     logger.info("Native library checker load failed", ex); 
    } 
} 

/** 
* When packaged into JAR extracts DLLs, places these into 
*/ 
private static void loadFromJar() { 
    // we need to put DLL in temp dir 
    String path = ***; 
    loadLib(path, JTDS_AUTH); 
} 

/** 
* Puts library to temp dir and loads to memory 
*/ 
private static void loadLib(String path, String name) { 
    name = name + ".dll"; 
    try { 
     // have to use a stream 
     InputStream in = net.sourceforge.jtds.jdbc.JtdsConnection.class.getResourceAsStream(LIB_BIN + name); 
     // always write to different location 
     File fileOut = new File(System.getProperty("java.io.tmpdir") + "/" + path + LIB_BIN + name); 
     logger.info("Writing dll to: " + fileOut.getAbsolutePath()); 
     OutputStream out = FileUtils.openOutputStream(fileOut); 
     IOUtils.copy(in, out); 
     in.close(); 
     out.close(); 
     System.load(fileOut.toString()); 
    } catch (Exception e) { 
     logger.error("Exception with native library loader", e); 
     JOptionPane.showMessageDialog(null, "Exception loading native libraries: " + e.getLocalizedMessage(), "Exception", JOptionPane.ERROR_MESSAGE); 
    } 
} 

正如你所看到的,我基本上覆制了逐字第一環節的解決方案,有一些小的修改,只是試圖讓應用程序運行。我還從第二個鏈接中複製了該類,並將其命名爲NativeLibraries,該方法的調用相當不重要,但它顯示在日誌中。

反正這裏有上啓動應用程序日誌輸出的相關位:

2015-07-20 12:32:33 INFO - Attempting to load library ntlmauth.dll 
    2015-07-20 12:32:33 INFO - Writing dll to: C:\Users\***\lib-bin\ntlmauth.dll 
    2015-07-20 12:32:33 DEBUG - Loaded libraries: [C:\Program Files\Java\jre1.8.0_45\bin\zip.dll, C:\Program Files\Java\jre1.8.0_45\bin\prism_d3d.dll, C:\Program Files\Java\jre1.8.0_45\bin\prism_sw.dll, C:\Program Files\Java\jre1.8.0_45\bin\msvcr100.dll, C:\Program Files\Java\jre1.8.0_45\bin\glass.dll, C:\Program Files\Java\jre1.8.0_45\bin\net.dll, C:\Users\***\lib-bin\ntlmauth.dll] 
    2015-07-20 12:32:33 INFO - Application startup 
    *** 
    2015-07-20 12:32:36 ERROR - Database exception 
    java.sql.SQLException: I/O Error: SSO Failed: Native SSPI library not loaded. Check the java.library.path system property. 
at net.sourceforge.jtds.jdbc.TdsCore.login(TdsCore.java:654) ~[jtds-1.3.1.jar:1.3.1] 
at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:371) ~[jtds-1.3.1.jar:1.3.1] 
at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:184) ~[jtds-1.3.1.jar:1.3.1] 
at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.8.0_45] 
at java.sql.DriverManager.getConnection(Unknown Source) ~[na:1.8.0_45]  

可以看到,圖書館,的確,從日誌中的第三行「加載」(這是最後一項,如果你不喜歡滾動)。然而,我只是簡單地使用了我認爲可能使用本地庫的類(我也試過TdsCore類無濟於事),因爲示例說明了如何做到這一點,只是使用包中的隨機類需要英寸

有什麼我在這裏失蹤?我對JNI或ClassLoaders的內部工作不太熟悉,所以我可能會錯誤地加載它。任何意見或建議將不勝感激!

回答

1

Welp我想出了一個解決方法:我結束了使用JarClassLoader。這基本上需要將我的所有依賴項(包括Java和本機)複製到我的主.jar文件夾中的「libraries」文件夾中,並禁用IDE中的.jar簽名。然後,該應用程序由一個新類運行,該類僅創建一個新的JarClassLoader對象並運行「invokeMain」方法 - 一個示例位於網站上。整整一件事花了大約三分鐘,幾天後我的頭撞牆。

希望這有助於某人某天!