Java - jni4net Bridge - Deploying Jar with dll dependenices

2k Views Asked by At

I am creating a application utilizing jni4net and a few dll's provided by our vendor (that is to say I have no control over the dll's).

When developing the program in my IDE (Eclipse) I simply placed the jni4net jar's and associated dlls into the project folder of the workspace.

[directory of project in IDE][1]

The program runs fine within the IDE:

fs() throws IOException {

    Bridge.setVerbose(true);

    Bridge.init();

    Bridge.LoadAndRegisterAssemblyFrom(new java.io.File("Kratos_3.j4n.dll"));

    Bridge.LoadAndRegisterAssemblyFrom(new java.io.File("Kratos_3.dll"));

    fsod = new FactSetOnDemand();
}

output:

> loading core from C:\Users\therka\workspace - Copy\instHolders\jni4net.n-0.8.3.0.dll
loading jni4net.n-0.8.3.0, Version=0.8.3.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxx from C:\Users\therka\workspace - Copy\instHolders\jni4net.n-0.8.3.0.dll
loaded jni4net.n-0.8.3.0, Version=0.8.3.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxx from C:\Users\therka\workspace - Copy\instHolders\jni4net.n-0.8.3.0.dll
Initialized jni4net core
core loaded from C:\Users\therka\workspace - Copy\instHolders\jni4net.n-0.8.3.0.dll
loading Kratos_3.j4n, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null from C:\Users\therka\workspace - Copy\instHolders\Kratos_3.j4n.dll
loaded Kratos_3.j4n, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null from C:\Users\therka\workspace - Copy\instHolders\Kratos_3.j4n.dll
loading Kratos_3, Version=3.5.0.0, Culture=neutral, PublicKeyToken=null from C:\Users\therka\workspace - Copy\instHolders\Kratos_3.dll
loaded Kratos_3, Version=3.5.0.0, Culture=neutral, PublicKeyToken=null from C:\Users\therka\workspace - Copy\instHolders\Kratos_3.dll

Now when I export from the IDE into a runnable JAR I select the option saying 'Copy Required Libraries into a sub-folder next to the generated JAR'. In the directory where the jar is now located i place all libraries and dll's and run it from command prompt.

> C:\instHolder>java -jar instHolder.jar
09-29-17 (03:42:12 PM): 317 clients retreived...
09-29-17 (03:42:12 PM): Confirming JVM version: 64
09-29-17 (03:42:12 PM): Java Version confirmation: 1.8.0_144
09-29-17 (03:42:12 PM): setting verbose
loading core from C:\instHolder\instHolder_lib\jni4net.n-0.8.3.0.dll
loading jni4net.n-0.8.3.0, Version=0.8.3.0, Culture=neutral, PublicKeyToken=xxxxxxxxxx
from C:\instHolder\instHolder_lib\jni4net.n-0.8.3.0.dll
loaded jni4net.n-0.8.3.0, Version=0.8.3.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxfrom C:\instHolder\instHolder_lib\jni4net.n-0.8.3.0.dll
Initialized jni4net core
core loaded from C:\instHolder\instHolder_lib\jni4net.n-0.8.3.0.dll
09-29-17 (03:42:13 PM): setting j4n
loading Kratos_3.j4n, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null from C:\instHolder\Kratos_3.j4n.dll
loaded Kratos_3.j4n, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null from C:\instHolder\Kratos_3.j4n.dll
09-29-17 (03:42:13 PM): setting 3
loading Kratos_3, Version=3.5.0.0, Culture=neutral, PublicKeyToken=null from C:\instHolder\Kratos_3.dll
loaded Kratos_3, Version=3.5.0.0, Culture=neutral, PublicKeyToken=null from C:\instHolder\Kratos_3.dll
09-29-17 (03:42:13 PM): Press Enter key to continue onto FSOD...
Exception in thread "main" java.lang.UnsatisfiedLinkError: kratos_3.runtimeplatform.FactSetOnDemand.__ctorFactSetOnDemand0(Lnet/sf/jni4net/inj/IClrProxy;)V
        at kratos_3.runtimeplatform.FactSetOnDemand.__ctorFactSetOnDemand0(Native Method)
        at kratos_3.runtimeplatform.FactSetOnDemand.<init>(FactSetOnDemand.java:25)
        at instHolders.fs.<init>(fs.java:46)
        at instHolders.init.main(init.java:44)

The program crashes once i create a new FactSetOnDemand object (last line in code sample above)

I've also fed the libraries and dlls into the command line arguments and received the same error

java -jar instHolder.jar -Dfile.encoding=Cp1252 -classpath""C:\instHolders\bin;C:\Users\therka\Desktop\JavaAPIs\SQLServer\jtds-1.3.1.jar;C:\Users\therka\Desktop\JavaAPIs\Apache\Commons\commons-net-3.3.jar;C:\Users\therka\Desktop\JavaAPIs\commons-lang3-3.4-bin\commons-lang3-3.4\commons-lang3-3.4.jar;C:\Users\therka\Desktop\JavaAPIs\Apache\IO\commons-io-2.4.jar;C:\Users\therka\Desktop\JavaAPIs\MySQL\mysql-connector-java-5.1.30.jar;C:\instHolders\jni4net.j-0.8.3.0.jar;C:\instHolders\Kratos_3.j4n.jar;C:\instHolder\Kratos_3.dll;C:\instHolder\Kratos_3.j4n.dll;C:\instHolder\jni4net.n-0.8.3.0.dll"" instHolders.init

Ultimately resulting in the same unsatisfiedlinkerror.

Can someone point me in the right direction as to my issue? I am pretty sure its due to my export options and ultimately my directory layout.

Many thanks!

EDIT:

Still unable to get this working after banging my head against a wall, I added a process monitor to both the IDE and the command prompt .jar - from this I was able to get the command line arguments both use (see below).

COMMAND LINE ARGUMENTS-Parent PID: 10988, Command line: java  -jar instHolder.jar -Dfile.encoding=Cp1252 -classpath "C:\instHolders\bin;C:\Users\therka\Desktop\Java APIs\SQL Server\jtds-1.3.1.jar;C:\Users\therka\Desktop\Java APIs\Apache\Commons\commons-net-3.3.jar;C:\Users\therka\Desktop\Java APIs\commons-lang3-3.4-bin\commons-lang3-3.4\commons-lang3-3.4.jar;C:\Users\therka\Desktop\Java APIs\Apache\IO\commons-io-2.4.jar;C:\Users\therka\Desktop\Java APIs\MySQL\mysql-connector-java-5.1.30.jar;C:\instHolders\jni4net.j-0.8.3.0.jar;C:\instHolders\Kratos_3.j4n.jar" instHolders.init, Current directory: C:\instHolder\, Environment: 

=C:=C:\instHolder

=ExitCode=00000001

ALLUSERSPROFILE=C:\ProgramData

APPDATA=C:\Users\therka\AppData\Roaming

asl.log=Destination=file

CommonProgramFiles=C:\Program Files\Common Files

CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files

CommonProgramW6432=C:\Program Files\Common Files

COMPUTERNAME=xxxxxxxxxxx 

ComSpec=C:\Windows\system32\cmd.exe

FP_NO_HOST_CHECK=NO

HOMEDRIVE=P:

HOMEPATH=\

HOMESHARE=\\xxxxx-fp\data\Users\xxxxx

LOCALAPPDATA=C:\Users\therka\AppData\Local

LOGONSERVER=\\xxxxx

NUMBER_OF_PROCESSORS=4

OS=Windows_NT

Path=C:\ProgramData\Oracle\Java\javapath;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\oracle\product\10.2.0\client_1\bin;C:\Program Files (x86)\Sybase\Shared\PowerBuilder\;C:\Program Files (x86)\Sybase\Shared\PowerBuilder\;C:\Program Files\Java\jre7\bin\javaw.exe

PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

PROCESSOR_ARCHITECTURE=AMD64

PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 58 Stepping 9, GenuineIntel

PROCESSOR_LEVEL=6

PROCESSOR_REVISION=3a09

ProgramData=C:\ProgramData

ProgramFiles=C:\Program Files

ProgramFiles(x86)=C:\Program Files (x86)

ProgramW6432=C:\Program Files

PROMPT=$P$G

PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

PUBLIC=C:\Users\Public

SESSIONNAME=Console

SystemDrive=C:

SystemRoot=C:\Windows

TEMP=C:\Users\xxxxx\AppData\Local\Temp

TMP=C:\Users\xxxxx\AppData\Local\Temp

USERDNSDOMAIN=xxxxxxxxxxx .xxxxxxxxxxx 

USERDOMAIN=xxxxxxxxxxx 

USERNAME=xxxxx

USERPROFILE=C:\Users\xxxxx

windir=C:\Windows

IDE

"IDE ARGUMENTS - Parent PID: 9696, Command line: ""C:\Program Files\Java\jre1.8.0_141\bin\javaw.exe"" -Dfile.encoding=Cp1252 -classpath ""C:\Users\xxxxx\workspace - Copy\instHolders\bin;C:\Users\xxxxx\Desktop\Java APIs\SQL Server\jtds-1.3.1.jar;C:\Users\xxxxx\Desktop\Java APIs\Apache\Commons\commons-net-3.3.jar;C:\Users\xxxxx\Desktop\Java APIs\commons-lang3-3.4-bin\commons-lang3-3.4\commons-lang3-3.4.jar;C:\Users\xxxxx\Desktop\Java APIs\Apache\IO\commons-io-2.4.jar;C:\Users\xxxxx\Desktop\Java APIs\MySQL\mysql-connector-java-5.1.30.jar;C:\Users\xxxxx\workspace - Copy\instHolders\jni4net.j-0.8.3.0.jar;C:\Users\xxxxx\workspace - Copy\instHolders\Kratos_3.j4n.jar"" instHolders.init ""-Djava.library.path=c:\instHolder"", Current directory: C:\Users\xxxxx\workspace - Copy\instHolders\, Environment: 

ALLUSERSPROFILE=C:\ProgramData

APPDATA=C:\Users\xxxxx\AppData\Roaming

asl.log=Destination=file

CommonProgramFiles=C:\Program Files\Common Files

CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files

CommonProgramW6432=C:\Program Files\Common Files

COMPUTERNAME=xxxxxxxxxxx 

ComSpec=C:\Windows\system32\cmd.exe

FP_NO_HOST_CHECK=NO

HOMEDRIVE=P:

HOMEPATH=\

HOMESHARE=\\xxxxx-fp\data\Users\xxxxx

LOCALAPPDATA=C:\Users\xxxxx\AppData\Local

LOGONSERVER=\\xxxxx

NUMBER_OF_PROCESSORS=4

OS=Windows_NT

Path=C:/Program Files/Java/jre1.8.0_144/bin/server;C:/Program Files/Java/jre1.8.0_144/bin;C:/Program Files/Java/jre1.8.0_144/lib/amd64;C:\ProgramData\Oracle\Java\javapath;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\oracle\product\10.2.0\client_1\bin;C:\Program Files (x86)\Sybase\Shared\PowerBuilder\;C:\program files\java\jdk1.8.0_141\bin;C:\Program Files (x86)\Sybase\Shared\PowerBuilder\;C:\Program Files\Java\jre7\bin\javaw.exe;C:\Windows\system32;

PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

PROCESSOR_ARCHITECTURE=AMD64

PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 58 Stepping 9, GenuineIntel

PROCESSOR_LEVEL=6

PROCESSOR_REVISION=3a09

ProgramData=C:\ProgramData

ProgramFiles=C:\Program Files

ProgramFiles(x86)=C:\Program Files (x86)

ProgramW6432=C:\Program Files

PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

PUBLIC=C:\Users\Public

SESSIONNAME=Console

SystemDrive=C:

SystemRoot=C:\Windows

TEMP=C:\Users\xxxxx\AppData\Local\Temp

TMP=C:\Users\xxxxx\AppData\Local\Temp

USERDNSDOMAIN=xxxxxxxxxxx 

USERDOMAIN=xxxxxxxxxxx 

USERNAME=xxxxx

USERPROFILE=C:\Users\xxxxx

windir=C:\Windows"

Also from the process monitor I can see that the underlying issue is happening when the .jar unpacks the dll into classes and then goes to use the FactSetOnDemand.class.

Process Montiro output for IDE IDE Process Monitor Output You can see this running successfully and creating necessary classes.

Process Monitor output for runnable .jar Command Line Process Monitor Output This fails to create the classes.

1

There are 1 best solutions below

0
On BEST ANSWER

After a week of getting nowhere I was able to solve my issue with the assistance of the vendor's developer (Thanks Adrian!).

Ultimately my issue was a combination of factors:

  1. Export Options used when creating a runnable .jar from my IDE
  2. Folder layout of deployed runnable .jar
  3. paths used in my code

First, I was incorrectly exporting my code with the option 'Copy required libraries into a sub-folder next to generated .jar'. The correct option was to 'package the libraries into generated .jar' with the runnable .jar.

Second, I created a folder and exported the runnable .jar to it. Within that folder I created a sub-folder called lib (dosnt matter) which contains the necessary .dll's to run the program.

Third, I modified my code as follows:

    Bridge.setVerbose(true);

    Bridge.init(new File("C:\\Users\\therka\\Desktop\\jar\\lib\\jni4net.n.w64.v40-0.8.3.0.dll"));

    Bridge.LoadAndRegisterAssemblyFrom(new java.io.File("C:\\Users\\therka\\Desktop\\jar\\lib\\Kratos_3.j4n.dll"));

    fsod = new FactSetOnDemand();

The paths given into the jni4net Bridge.init & Bridge.LoadAndRegisterAssembly must point to the /lib/ folder containing the .dlls. Previously I was not specifying directories and as a result the .dlls were not found (causing unsatisifedLinkerror).

Now all you need is to open command prompt, cd to the directory with the .jar, and -java -jar the runnable.

Hope this saves someone the headaches I had to go through.