java - Manually loading native libraries to circumvent a restrictive environment -


i'm maintaining java swing application requires connection instance of microsoft sql server. various reasons, opted replace native sql server driver being used jtds (the aforementioned microsoft drivers not working @ time , have apparently failed in field well). when try run executable .jar outside of ide, run issues because i'm missing appropriate ntlmauth.dll dependency.

before proceeding, it's important note application being developed , used in extremely restrictive (windows-only) environment:

  • i cannot install software requires windows uac authentication
  • my users cannot install or run software requires uac authentication
  • this means cannot write files system32 or java_home, , cannot use sort of processbuilder tomfoolery start jvm whatever command line arguments need
  • i cannot use executable wrappers/installers require uac permission first time installation/setup

the solution i'm trying combination of this one , this 1 check it--essentially packaging .dll inside of .jar, extracting , loading if necessary--as of other solutions i've found have been incompatible above restrictions; however, i'm running issue after native library ostensibly "loaded," exception saying isn't.

my pre-startup code:

private static final string lib_bin = "/lib-bin/"; private static final string jtds_auth = "ntlmauth";  // load required jtds binaries static {     logger.info("attempting load library {}.dll", jtds_auth);     try {         system.loadlibrary(jtds_auth);     } catch (unsatisfiedlinkerror e) {         loadfromjar();     }      try {         // quick checks make sure 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 jar extracts dlls, places these  */ private static void loadfromjar() {     // need put dll in temp dir     string path = ***;     loadlib(path, jtds_auth); }  /**  * puts library temp dir , loads memory  */ private static void loadlib(string path, string name) {     name = name + ".dll";     try {         // have use stream         inputstream in = net.sourceforge.jtds.jdbc.jtdsconnection.class.getresourceasstream(lib_bin + name);         // write 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 native library loader", e);         joptionpane.showmessagedialog(null, "exception loading native libraries: " + e.getlocalizedmessage(), "exception", joptionpane.error_message);     } } 

as can see, copied solution first link verbatim, few minor modifications try , application running. copied class second link , named nativelibraries, invocation of method irrelevant shows in logs.

anyway here relevant bits of log output on starting application:

    2015-07-20 12:32:33 info  - attempting 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 java.library.path system property. @ net.sourceforge.jtds.jdbc.tdscore.login(tdscore.java:654) ~[jtds-1.3.1.jar:1.3.1] @ net.sourceforge.jtds.jdbc.jtdsconnection.<init>(jtdsconnection.java:371) ~[jtds-1.3.1.jar:1.3.1] @ net.sourceforge.jtds.jdbc.driver.connect(driver.java:184) ~[jtds-1.3.1.jar:1.3.1] @ java.sql.drivermanager.getconnection(unknown source) ~[na:1.8.0_45] @ java.sql.drivermanager.getconnection(unknown source) ~[na:1.8.0_45]     

one can see library was, indeed, "loaded," third line in log (it's last entry, if don't feel scrolling). however, used class felt using native libraries (i tried tdscore class no avail), example showed how using random class package library needed in.

is there i'm missing here? i'm not experienced jni or inner workings of classloaders, might loading wrong. advice or suggestions appreciated!

welp figured out workaround: ended using jarclassloader. entailed copying dependencies, both java , native, "libraries" folder within main .jar, , disabling .jar signing in ide. application run new class creates new jarclassloader object , running "invokemain" method--an example on website. whole thing took 3 minutes, after several days of banging head against wall.

hope helps someday!


Comments