Most Java/.NET interop demos stop at returning a string. Logging is a better test: it touches a real Java library, configuration, object marshalling, and two runtimes that need to produce one coherent output.
This walkthrough uses JNBridgePro 12.1 to call Apache log4j from C#. The .NET and Java code both write through the same Java logging stack, so their messages appear together under one configuration.
What we are building
The finished console application does three things:
- calls log4j classes directly from C# through generated .NET proxies
- invokes an existing Java class whose
doIt()method also logs through log4j - runs with either an in-process shared-memory bridge or a separate Java process over TCP/binary
The example uses log4j, but the workflow is the same for any Java JAR or class library that a .NET application needs to reuse.
Prerequisites
You will need:
- a Java JDK
- the .NET SDK and, for this demo target, the .NET Framework 4.8 targeting pack
- JNBridgePro 12.1 (an evaluation license is enough)
-
log4j.jar,log4j-core.jar, and the compiledloggerDemo.JavaClass
The sample files ship in demos\tutorials\logDemo.zip. This walkthrough assumes they are unpacked under C:\NewGui\LogDemo.
1. Build the Java classpath in JNBProxy
Launch JNBProxy and choose Create new .NET → Java project.
Add both log4j JARs to the classpath, then add the folder containing the loggerDemo package. You can drag the files and folder into the classpath panel or use Edit classpath….
Next, load the types:
- Use Add Classes from JAR for
log4j.jar. - Repeat for
log4j-core.jar. - Use Add Classes from Classpath for
loggerDemo.JavaClass. - Leave Include supporting classes enabled.
Select the classes you want to expose, click Add+, and build the proxy assembly as LoggerDemoProxy.dll.
The generated assembly gives C# a typed surface for the Java APIs. Package names become .NET namespaces, and Java methods appear as methods on the proxy classes.
2. Export a runnable .NET project
From the exposed-proxies gear menu, choose Export demo project… and select the proxy DLL you just built.
Name the project LoggerDemo, choose .NET Framework 4.8 (Windows), and export it. JNBProxy can also export projects for modern .NET on Windows or Linux.
One easy mistake matters here: do not give the project the same name as the proxy assembly. A project called LoggerDemoProxy would emit an assembly that collides with LoggerDemoProxy.dll. Keeping the project as LoggerDemo avoids that runtime failure.
The export includes:
LoggerDemo.sln- a C# console project with references to the proxy assembly and JNBridge runtime
- shared-memory and TCP configuration files
- the Java-side runtime and classpath files
env.bat- one-click build/run scripts for both communication modes
- a README explaining the generated layout
That starter project is useful beyond demos: it provides a known-good baseline before you fold the bridge into a larger solution.
3. Prove the generated bridge first
Set JAVA_HOME in env.bat. The script derives the 64-bit jvm.dll path used by shared-memory mode; you can also confirm that path in the generated App.config.
Run buildAndRunSharedMem.bat before adding application logic. The exported stub round-trips a call through java.lang.Object. If it prints a Java hash string, the JVM, classpath, and proxy runtime are connected.
If you instead get ClassNotFoundException or NoClassDefFoundError, check for a moved JAR, an incorrect class-folder root, or missing read permissions. Fix the classpath before debugging the C# code.
4. Call log4j from C
Replace the generated Program.cs with this:
using System;
using org.apache.log4j;
using java.lang;
using loggerDemo;
namespace LoggerDemo
{
class Program
{
static Category cat =
Category.getInstance("com.jnbridge.demos.logger.LoggerDemo");
[STAThread]
static void Main(string[] args)
{
BasicConfigurator.configure();
cat.info(new JavaString("Entering application"));
DotNetClass dotNetClass = new DotNetClass();
JavaClass javaClass = new JavaClass();
for (int i = 0; i < 5; i++)
{
dotNetClass.Log();
javaClass.doIt();
}
cat.info(new JavaString("Exiting application"));
}
}
public class DotNetClass
{
static Category cat =
Category.getInstance("com.jnbridge.demos.logger.DotNetClass");
public void Log()
{
cat.debug(new JavaString("Logged from .NET"));
}
}
}
There are three details worth noticing.
First, the using directives mirror Java package names: org.apache.log4j, java.lang, and loggerDemo. The application calls Category, BasicConfigurator, and JavaClass as typed APIs, with IntelliSense available in Visual Studio.
Second, the strings passed to info() and debug() are wrapped in java.lang.JavaString. Those overloads expect a Java Object; a CLR string is not itself a Java object, while the proxy wrapper is.
Third, the loop alternates a .NET-originated logging call with JavaClass.doIt(). Both ultimately use the same log4j configuration and output.
Run buildAndRunSharedMem.bat again. You should see the Java and .NET messages interleaved in one console log.
Shared memory versus TCP
The exported project supports two topologies.
Shared-memory mode loads the JVM into the .NET process:
<dotNetToJavaConfig
scheme="sharedmem"
jvm64="C:\Program Files\Java\jdk-11\bin\server\jvm.dll"
jvm32=""
jnbcore="jnbcore.jar"
bcel="bcel-6.10.0.jar"
classpath=".;log4j.jar;log4j-core.jar;C:\NewGui\LogDemo"
/>
This is the simplest and fastest option when both runtimes can live in one process. The JVM starts automatically before the first proxy call.
TCP/binary mode keeps Java in a separate process:
<dotNetToJavaConfig
scheme="jtcp"
host="localhost"
port="8085"
useSSL="false"
/>
In this topology, the Java classpath moves to the Java-side configuration. buildAndRunTCP.bat builds the .NET project, starts the Java side, runs the demo, and shuts Java down afterward. TCP mode also supports SSL and class whitelisting for tighter deployment boundaries.
The reusable pattern
The useful part of this demo is not log4j itself. It is the repeatable integration sequence:
- add the Java JARs and class folders
- expose the required classes and generate typed proxies
- export a working starter project
- prove the bridge before adding application code
- choose shared memory or TCP based on deployment needs
That lets a .NET team reuse a proven Java library without translating it, wrapping every method in HTTP, or hiding integration details behind string-based runtime calls.
The complete illustrated walkthrough, including every JNBProxy screen and the generated project layout, is available in the original JNBridge guide.
Top comments (0)