Calling a Java Logging Package from .NET
On this page
Introduction
This guide shows how JNBridgePro is used to build a .NET console application that calls Java classes from C#. We generate .NET proxies for log4j, the Apache Java logging package, and for an existing Java class, loggerDemo.JavaClass, whose method doIt() logs a message through log4j. A .NET class then logs through the same proxies, so Java- and .NET-originated messages appear interleaved in a single log4j output and logging is controlled from a single configuration — a common requirement when integrating .NET code with an existing Java codebase.
JNBProxy’s demo project export does the .NET-side setup automatically: it creates a Visual Studio solution wired to the generated proxy assembly and the JNBridgePro runtime, adds configuration files for both shared-memory and TCP communications, copies the Java-side components, and generates scripts that build and run the demo with a single command. No manual project configuration is required.
What you’ll need
- A Java JDK, and the .NET SDK with the .NET Framework 4.8 targeting pack.
- JNBridgePro v12.1 — download and install it from jnbridge.com; a free evaluation license is enough to run this demo.
- The demo files — log4j.jar, log4j-core.jar, and the class folder loggerDemo containing JavaClass.class — installed with JNBridgePro in demos\tutorials\logDemo.zip. In this guide they are unpacked to C:\NewGui\LogDemo.
The log4j files are just the example — everything below works identically with your own code. Substitute your own JARs and class folders on the classpath, expose the classes you need, and JNBProxy will generate proxies for them and export a ready-to-run starter project around them in exactly the same way.
Generating the proxies
Launch JNBProxy and select Create new .NET → Java project (Figure 1). The main window (Figure 2) walks through proxy generation in four numbered steps: build a classpath, load classes from it into the environment, choose the classes to expose, and build the proxy assembly. Progress and diagnostics appear in the Output pane at the bottom.


1Set up the classpath
Drag log4j.jar and log4j-core.jar from Windows Explorer onto the drop target (or click Edit classpath…), then do the same for the folder containing the loggerDemo class folder — here, C:\NewGui\LogDemo. Added entries appear as chips at the top of the Classpath panel (Figures 3 and 4).


The Edit Class Path dialog (Figure 5) shows each entry’s full path; entries can also be added by path (Add…) or removed (×) here.

2Load classes into the environment
Open Add Classes from JAR and pick log4j.jar (Figure 6); repeat for log4j-core.jar. For the single class JavaClass, use Add Classes from Classpath: type to search, check loggerDemo.JavaClass, leave Include supporting classes checked, and click OK (Figure 7). The Output pane shows the classes loading into the Environment tree.


3Choose the classes to expose
We want proxies for all of these classes: check Select all in the Environment panel and click Add+ (Figure 8), which adds every checked class — plus all supporting classes — to the Exposed proxies pane (Figure 9).


4Build the proxy assembly
Click Build and choose a name and location for the assembly that will contain the generated proxies — here, LoggerDemoProxy.dll. Generation takes a minute or two; BUILD COMPLETED appears in the Output pane when it finishes.
Exporting a demo project
JNBProxy can now wrap the proxies in a complete, runnable .NET project. In the Exposed proxies panel, open the gear menu and choose Export demo project… (Figure 10), and select the proxy DLL you just built. Then name the project, pick its type and location, and click Export (Figure 11) — here the project is LoggerDemo, of type .NET Framework 4.8 (Windows), created in C:\NewGui. Projects can also be exported for .NET 8 on Windows or Linux.
Warning: Give the project a name that is different from the proxy assembly’s name. If the project name matches the proxy DLL (for example, a project named LoggerDemoProxy wired to LoggerDemoProxy.dll), the project’s own output assembly collides with the proxy assembly and the demo fails at runtime. Here the proxy is LoggerDemoProxy.dll and the project is LoggerDemo.


The exported folder (Figure 12) contains everything the demo needs:
- LoggerDemo.sln
- LoggerDemo\ — an SDK-style C# console project already referencing LoggerDemoProxy.dll and JNBShare.dll, with the native JNBridge DLLs copied on build, and configuration files for both modes (App.config — shared memory; App.tcp.config — TCP);
- Java Side\ — jnbcore.jar and bcel (the JNBridge Java-side runtime), copies of the classpath JARs, the Java-side properties file, an optional class whitelist, and a manual start script for TCP mode;
- env.bat — the Java locations used by the run scripts;
- buildAndRunSharedMem.bat / buildAndRunTCP.bat — one-click build and run for each communication mode;
- ReadMe.md — how the project fits together.

How these pieces fit together — what each file does, how the shared-memory bridge is configured, and how to adapt the same layout to your own application — is described in the knowledge-base article Call Java from .NET Project: Anatomy of a Shared Memory Bridge.
Running the demo
1Point env.bat at your JVM
Open env.bat (Figure 13) and set JAVA_HOME to your JDK root; JVM_DLL_64, the 64-bit jvm.dll used in shared-memory mode, is derived from JAVA_HOME by default.
The jvm.dll path that JNBProxy itself was configured with is recorded in LoggerDemo\App.config (the jvm64 attribute) and can be copied from there.

2Prove the bridge
Double-click buildAndRunSharedMem.bat. It builds the project, writes the shared-memory configuration (with the JVM paths from env.bat) next to the executable, and runs it. The exported Program.cs starts as a stub that round-trips a call through the bridge using java.lang.Object, which is included in every proxy assembly — a printed Java hash string means the bridge is up and running (Figure 14).
If the run fails with a ClassNotFoundException or NoClassDefFoundError instead, the JVM could not load one of the classpath entries — most often a moved JAR or class folder, or missing read permissions on one of them. See “Handling ClassNotFoundException and NoClassDefFoundError” in the Anatomy knowledge-base article for the causes and fixes.

3Add the demo code
Replace the contents of LoggerDemo\Program.cs with the following:
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"); /// <summary> /// The main entry point for the application. /// </summary> [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.f(); javaClass.doIt(); } cat.info(new JavaString("Exiting application")); } } public class DotNetClass { static Category cat = Category.getInstance("com.jnbridge.demos.logger.DotNetClass"); public void f() { cat.debug(new JavaString("Logged from .NET")); } } }
A few things worth noticing:
- Proxy namespaces match the Java package names — we import org.apache.log4j, java.lang, and loggerDemo, then use Category, BasicConfigurator, and JavaClass exactly as they would be used in Java.
- Strings passed to info() and debug() are wrapped in java.lang.JavaString: those methods take a java.lang.Object, which a .NET string is not, but JavaString is.
- The solution can be opened in Visual Studio, where IntelliSense completes method calls on the Java proxies just as it does for .NET classes.
4Run it
Run buildAndRunSharedMem.bat again. The console now shows logging messages originating on both the .NET and Java sides, interleaved in a single log4j output (Figure 15).

In shared-memory mode the Java side runs inside the .NET process — the JVM is loaded automatically before the first proxy call, so nothing needs to be started explicitly. It is the fastest communication mechanism and the simplest way to run the demo.
Using TCP/binary communications
The exported project can also run the Java side as a separate process, communicating over TCP/binary. The difference is visible in the two configuration files in the LoggerDemo project folder. App.config (shared memory) hosts the JVM in the .NET process, so it carries the JVM location and the Java classpath:
<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" />
App.tcp.config (TCP) only needs to say where the Java side is listening:
<dotNetToJavaConfig scheme="jtcp" host="localhost" port="8085" useSSL="false" />
In TCP mode the classpath and the rest of the Java-side configuration move to the Java side: it is started with jnbcore.jar on the classpath and the properties file jnbcore_tcp_no_security.properties (see “start Java side.bat” in the Java Side folder), and listens on port 8085. buildAndRunTCP.bat automates the whole sequence: build, swap in App.tcp.config, start the Java side, run the demo, and shut the Java side down afterwards.
With TCP, the Java side can also be restricted to serve only specific classes (class whitelisting — classWhiteList.txt and the javaSide.useClassWhiteList / javaSide.classWhiteListFile properties), and communications can be secured with SSL. See the Users’ Guide for both.
Summary
This demo integrated Java and .NET logging in three short stages: JNBProxy generated .NET proxies for the log4j classes and loggerDemo.JavaClass; the demo project export wrapped them in a fully configured solution; and the demo code dropped into Program.cs and ran with a single script, over shared memory or TCP. Java- and .NET-originated messages flow to one log4j output under one configuration — and by allowing Java and .NET code to interoperate like this, JNBridgePro helps developers derive full value from existing Java code as they take advantage of the .NET platform. The same three steps apply to any Java library or class you need to reach from C# — and they work in the other direction too, as the companion Java → .NET demo guide shows.
