A quick jni4net performance hack
💻 coding

A quick jni4net performance hack

2 min read 326 words
2 min read
ShareWhatsAppPost on X
  • 1jni4net simplifies Java JNI integration with C# libraries, enhancing performance on Windows platforms.
  • 2A performance hack can reduce Java-to-DLL call time by up to 100x for methods without type marshaling.
  • 3The hack involves modifying generated C# methods to set up thread cache correctly, improving efficiency.

AI-generated summary · May not capture all nuances

Key Insight
AskGif

"jni4net simplifies Java JNI integration with C# libraries, enhancing performance on Windows platforms."

A quick jni4net performance hack

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 
}

Enjoyed this article?

Share it with someone who'd find it useful.

ShareWhatsAppPost on X

AskGif

Published on 19 June 2019 · 2 min read · 326 words

Part of AskGif Blog · coding

You might also like