jni4net is a great library that creates Java proxies for Microsoft based C# libraries on the Windows platform. It makes Java JNI easy with good performance. You follow these processes to use jni4net
Create your C# library
Run proxygen to generate Java native library source code and C# adapter source that shims in between Java and the original library.
Run javac to compile the java code
Create a jar file of the compiled java code
Run the .Net csc.exe that comes with the default .Net installation to compile the C# code
Create a new DLL of the just compiled C# code
Create a Java program that uses the new generated Jar file, the generated C# dll, and the original C# dll.
I found a quick hack that improves the performance of the jni4net bridge that involves inserting a line of code in each generates C# method. This hack improves the Java-to-DLL call time only. It does not impact the performance of the Java code on one side or the C# code on the other. It lowers the overhead of highly repetitive method calls by up to 100x for methods with no type marshaling. Each method looks something like this:
private static void IncrementBy1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class, int counterKey, long incrementAmount) {
// (IJ)V
// (IJ)V
global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp);
try {
global::FreemanSoft.PerformanceCounters.WindowsPerformanceFacade.IncrementBy(counterKey, incrementAmount);
}catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);}
}
I add one line of code that makes the method look like this:
This Powershell script modifies all jni4net generated methods to add the code shown above.
echo "Hacking generated JNI C# files"
$pathtofiles = "generated\clr"
$oldregex = "global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap"
$new = "// quick hack to get the thread cache correctly set up because the Wrap doesn't do that
global::net.sf.jni4net.jni.JNIEnv @__ignored = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv;
global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap"
Get-Childitem $pathtofiles -recurse -name -Include *.cs | ForEach {
#echo ":::: $pathtofiles\$_"
$fullpath = "$pathtofiles\$_"
(Get-Content $fullpath | ForEach {$_ -replace "global::net.sf.jni4net.jni.JNIEnv \@__env = global::net.sf.jni4net.jni.JNIEnv.Wrap", "$new"}) | Set-Content $fullpath
}


