Calling a Java Logging Package from .NET

JNBridgePro — the fastest, easiest way to bridge Java and .NET in production. Generate proxies in minutes, call Java from C# (or C# from Java) with native syntax — trusted by enterprises worldwide. Learn more · Download free trial

JNBridgePro Demo Guide Version 12.1 .NET → Java C# · log4j

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.

The Launch JNBProxy dialog with Create new .NET to Java project selected
Figure 1 — JNBProxy launch form
The JNBProxy main window for a .NET to Java project, with its four numbered panels
Figure 2 — The JNBProxy main window

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 Classpath panel with log4j.jar and log4j-core.jar added as chips
Figure 3 — The two log4j JARs added
The Classpath panel after the LogDemo class folder is added
Figure 4 — …then the class folder

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

The Edit Class Path dialog listing the full path of each classpath entry
Figure 5 — The Edit Class Path dialog

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.

The Add Classes from JAR command loading log4j.jar
Figure 6 — Loading classes from a JAR
The Add Classes from Classpath dialog with loggerDemo.JavaClass checked and Include supporting classes enabled
Figure 7 — Selecting loggerDemo.JavaClass from the classpath

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).

The Environment panel with Select all checked and the Add+ button
Figure 8 — Select all, then Add+
The Environment and Exposed proxies panes after Add+, with the log4j and loggerDemo classes exposed
Figure 9 — Environment and Exposed proxies after Add+

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.

Export demo project command in the Exposed proxies gear menu
Figure 10 — Export demo project… in the gear menu
The Export demo project dialog naming the project LoggerDemo and choosing .NET Framework 4.8 (Windows)
Figure 11 — Naming the project and choosing its type

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.
The exported demo project folder in File Explorer
Figure 12 — The exported project

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.

env.bat with JAVA_HOME and JVM_DLL_64 settings
Figure 13 — env.bat

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.

Console output of the exported stub proving the bridge: a Java hash string printed from java.lang.Object
Figure 14 — The exported stub proving the bridge

3Add the demo code

Replace the contents of LoggerDemo\Program.cs with the following:

Program.cs
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).

Console output showing log4j messages logged from .NET and from Java interleaved in one log
Figure 15 — Java- and .NET-originated messages in one log

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:

App.config
<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:

App.tcp.config
<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.

Run it yourself Download JNBridgePro v12.1 with a free evaluation license — the log demo ships with it in demos\tutorials\logDemo.zip — or browse the other JNBridgePro demos.
Download JNBridgePro