We made a number of exciting changes in the Javonet 1.4 release, which include rebuilding the fundamental modules and creating a new full binary communication protocol. We are proud to reveal the result of these modifications—the fastest and the most reliable Java to .NET bridge ever created. Additionally, we are constantly putting a lot of effort into simplifying the APIs, extending the flexibility, and adding great new features, which are detailed in further sections of the text.
Most of the important changes in this release stem from the new full binary protocol:
- Incredibly high performance was achieved by decreasing the call overhead to as low as 0.000009 seconds.
- Improved thread life cycle management
- Improved data type translation performance
- Decreased amount of data transferred between .NET and Java
New base for higher reliability and incredible performance
As an ongoing commitment to making Javonet calls as close as possible to native calls, in this release, we decided to completely redesign the communication protocol, which is used as a transfer envelope for data being sent between Java and .NET. The new protocol is entirely based on binary frames, which allow us to minimize the size of messages to almost only the length of the data stored in the variables. Using a new data types and message conversion mechanism, we dramatically cut the time for the executions.
Pushing the performance limits even further, in this release, we made it possible to leverage Javonet possibilities in high-frequency computing scenarios by achieving approximately nine microseconds of call overhead time. It means that when any method is invoked on the .NET side, Javonet adds only about nine millionths of a second! Such performance makes it possible to achieve up to 100,000 calls to .NET per second on an average i7 CPU.
Sample Java Test Calling 250 000x .NET Method With One Argument and Result:
@Test public void test_InvokeMethodWithCharArgPerformance() throws JavonetException { for (int repeat=0; repeat<5; repeat++) { NObject sampleObj = Javonet.New("Sample"); long startTime = System.currentTimeMillis(); for (int i=0; i<250000;i++) { Character myChar=sampleObj.<Character>invoke("ReturnChar",'c'); } long stopTime = System.currentTimeMillis(); double elapsedTime = (stopTime - startTime); System.out.println("Time Elapsed [ms]: "+elapsedTime); double avgCallTime = elapsedTime / 250000F; System.out.println("Avareage Call Time [ms]: "+avgCallTime); } }
Console Output
Time measured include execution time on .NET side plus time needed to pass the call and retrieve result by Javonet achieving on average a fraction of a hundredth of a millisecond:
Thread management improved
By aiming for the highest performance, an exciting improvement in thread management was reached. Javonet 1.4 guarantees exactly one Java thread for each .NET thread, the life cycle of which will be bound to the life cycle of the associated thread. With this approach, in case of multiple .NET event calls subscribed on the Java side, each event will reuse the same thread that was associated with the thread generating events on the .NET side. Moreover, we have deeply examined the details of multithread application performance, traced each point where Javonet logic might have been adding thread synchronization in order to perform internal operations, and either removed, optimized, or modified them to write-only thread locking.
Key modules updated
We have focused on all key modules of Javonet internals like methods and fields caching mechanisms, garbage collector forwarding, and events handling, making them perform better as well.
All of these changes result in higher reliability and better memory management for the solutions powered by Javonet; mixing this with astonishing performance, we receive an effortless bridging solution that is almost transparent for developers.
Generics support extended
Javonet 1.4 is characterized by the extended functionality of APIs that provide access to .NET generics. By extending the existing mechanism responsible for calling generic methods, we added the possibility of initializing the generic class with any number of generic types. Because of this, users got unlimited access to generic dictionaries, lists, interfaces, and other generic objects. Regular calling of generic methods has been improved as well by adding support for “ref” and “out” arguments, which are available only in nongeneric methods so far.
Support for .NET COM objects’ interop assemblies
Considering the needs of developers who use Javonet, we have added support for .NET COM objects’ interop assemblies. If you have your own or third-party .NET DLLs or SDK that exposes access to COM objects by providing wrapping interop assemblies, you will now be able to use them in Java without any limitations, just like any other .NET object.
This is possible thanks to the built-in support of MarshalByRefObjects. Objects of this kind are usually returned from interop assemblies as reference to COM objects. In .NET, you access these objects using interfaces delivered in an interop assembly. Now Javonet is able to automatically detect such objects and find the matching interface to resolve the method or field that you want to access from the Java side.
.NET 4.5 and Java 8 compatibility
To make sure that Javonet may be used with the latest technology, we guarantee that Javonet 1.4 is fully compatible with Java 8 and supports .NET 4.5 libraries.
Additionally, choosing the right .NET framework is now easier than ever before. All .NET frameworks have been built into the single JAR file. To choose the one to be loaded, all you have to do is provide the appropriate JavonetFramework enum value as the last argument of your activate method. Optionally, a .NET framework may be configured using the XML configuration file.
API usability improved
Several tiny improvements have been introduced in Javonet API as well. The most important of them are listed below:
Autoresolving enum types’ namespaces
Now when there is only one type in loaded assemblies with the name of your enum, you do not need to provide the full namespace while initializing the NEnum class. Using just the type name, Javonet will automatically resolve the namespace, making your code more readable. As a good example, have a look at the following DialogResult enum usage:
if (myDialog.<NEnum>invoke("ShowDialog")==new NEnum("DialogResult","OK")) { //(…my logic…) }
NType as a method argument: Calling method with typeof(type) enabled
We added support for NType objects in method arguments. If your .NET code expects “Type” as an argument, you can pass the NType object instance as a counterpart of the “typeof(type)” syntax.
Calling sample method with Type argument in C#:
myObj.MethodWithTypeArgument(typeof(String)); //calling in .NET
Same operation from Java
NType stringType = Javonet.getType("tring"); myObj.invoke("MethodWithTypeArgument", stringType); //calling from Java
Garbage collection performance improved
Fundamental changes have been introduced in the garbage collector forwarding mechanism. When you store a reference to a .NET object in Java using our NObject variable, the removal of that object by Java garbage collector is automatically forwarded to the .NET side. The time needed to process these calls has been significantly decreased. Nevertheless, we have also introduced a new DelayGcContext class, which allows users expecting more then 500,000 collections per minute to mark a specific part of the code to use a GC batching mechanism. For all instances of NObjects used between “Begin()” and “End()” method calls on the “DelayGcContext” class, the garbage collection events will be grouped into batches of 100,000 objects. If the size limit will not be reached within 30 seconds, then the buffer will be flushed as well.
Simplified and clarified Javonet dependencies
Javonet is a single-file solution and theoretically does not require any additional components to be installed. However, while it connects Java and .NET, Java Runtime and .NET Framework are required for proper usage. Because part of Javonet is written in native code, it also requires the VC++ runtime, which is usually already installed on most computers. This last dependency seemed to cause a bit of confusion among the developers using Javonet for the first time. Therefore, the new release has a built-in missing dependency detection mechanism, which reports which version of VC++ and .NET is needed in a clean and easy way within the exception message, providing the appropriate URLs for immediate download. For more details, please check the summary below:
Note: Before using Javonet, make sure you have JDK 1.6 or newer and the following prerequisites installed:
For use with .NET Framework 3.5 (supports .NET 3.5 DLLs):
Visual C++ Runtime 2008: x86 or x64 depending on your JDK/JRE architecture.
.NET Framework 3.5: Download here.
For use with .NET Framework 4.0 (supports .NET 4.0 and 3.5 DLLs):
Visual C++ Runtime 2010: x86 or x64 depending on your JDK/JRE architecture.
.NET Framework 4.0: Download here.
For use with .NET Framework 4.5 (supports .NET 4.5, 4.0, and 3.5 DLLs):
Visual C++ Runtime 2013: x86 or x64 depending on your JDK/JRE architecture.
.NET Framework 4.5: Download here.