DEV Community

Cover image for Calling Java from VB.NET: Every Option from REST to In-Process Bridging
JNBridge
JNBridge

Posted on • Originally published at jnbridge.com

Calling Java from VB.NET: Every Option from REST to In-Process Bridging

If you've ever Googled "call Java from VB.NET" and gotten nothing but abandoned StackOverflow threads from 2014, you're not alone. VB.NET is quietly running millions of enterprise apps — financial platforms, healthcare systems, logistics — and those teams increasingly need to tap into Java libraries they can't rewrite.

I spent a week mapping out every approach that actually works in 2026. Here's what I found.

The Problem: Two Runtimes, No Shared Anything

VB.NET runs on the .NET CLR. Java runs on the JVM. They don't share memory, type systems, or calling conventions. If you need Apache PDFBox for PDF generation, or a proprietary Java pricing engine your company spent years building, you can't just Imports com.acme.pricing and go.

Or can you?

Option 1: REST/HTTP APIs

The obvious approach — wrap your Java code in a Spring Boot service, call it via HttpClient.

Pros: Language-agnostic, works across networks, everyone understands HTTP.

Cons: 2-15ms per call. JSON serialization overhead. You need a separate running Java service. Fine for occasional calls, painful when you're making thousands per second.

' The REST approach — works but adds overhead
Dim client As New HttpClient()
Dim response = Await client.GetAsync("http://localhost:8080/api/price?product=ABC")
Dim json = Await response.Content.ReadAsStringAsync()
Enter fullscreen mode Exit fullscreen mode

Option 2: gRPC

Binary protocol, Protocol Buffers, lower latency than REST.

Pros: ~0.5-2ms per call, strongly typed, streaming support.

Cons: Still needs a separate Java process. Protobuf schema management. VB.NET gRPC support exists but isn't as polished as C#'s.

Option 3: Message Queues

Publish/subscribe through RabbitMQ or Kafka. Async by nature.

Pros: Decoupled, scalable, resilient.

Cons: Not suitable for synchronous request/response. More infrastructure to manage. Overkill when you just need to call a method and get a result.

Option 4: In-Process Bridge (the one I'd pick)

A bridge like JNBridgePro loads the JVM directly into your .NET process and generates .NET proxy classes for Java objects. Your VB.NET code calls Java methods with native syntax — no HTTP, no serialization, no separate service.

' Java's HashMap, used natively from VB.NET
Imports java.util

Dim map As New HashMap()
map.put("key", "value")
Dim result As String = CStr(map.get("key"))
Enter fullscreen mode Exit fullscreen mode

That's not pseudocode. That actually compiles and runs.

Real Code: PDFBox from VB.NET

Apache PDFBox is Java's go-to PDF library. With proxy classes generated, VB.NET uses it directly:

Imports org.apache.pdfbox.pdmodel
Imports org.apache.pdfbox.pdmodel.font

Public Sub CreatePDF()
    Dim document As New PDDocument()
    Dim page As New PDPage()
    document.addPage(page)

    Dim contentStream As New PDPageContentStream(document, page)
    contentStream.setFont(PDType1Font.HELVETICA_BOLD, 14)
    contentStream.beginText()
    contentStream.newLineAtOffset(50, 700)
    contentStream.showText("Generated from VB.NET via JNBridgePro")
    contentStream.endText()
    contentStream.close()

    document.save("C:\output\report.pdf")
    document.close()
End Sub
Enter fullscreen mode Exit fullscreen mode

No REST endpoint. No separate service. Just call the Java API like it's a .NET library.

Real Code: Apache Kafka Producer

Instead of hunting for a third-party .NET Kafka client, use the official Java client directly:

Imports org.apache.kafka.clients.producer
Imports java.util

Public Sub SendKafkaMessage(topic As String, message As String)
    Dim props As New Properties()
    props.put("bootstrap.servers", "kafka-broker:9092")
    props.put("key.serializer", _
        "org.apache.kafka.common.serialization.StringSerializer")
    props.put("value.serializer", _
        "org.apache.kafka.common.serialization.StringSerializer")

    Dim producer As New KafkaProducer(props)
    Dim record As New ProducerRecord(topic, "key", message)
    producer.send(record)
    producer.flush()
    producer.close()
End Sub
Enter fullscreen mode Exit fullscreen mode

Real Code: Proprietary Java Business Logic

The most common scenario — your org has a Java pricing engine or risk model that took years to build. Rewriting it in VB.NET isn't realistic.

Imports com.acme.pricing

Public Function CalculatePrice(productId As String, quantity As Integer) As Decimal
    Dim engine As New PricingEngine()
    engine.loadRules("pricing-rules-2026.xml")

    Dim request As New PriceRequest()
    request.setProductId(productId)
    request.setQuantity(quantity)
    request.setCurrency("USD")

    Dim result As PriceResult = engine.calculate(request)
    Return CDec(result.getTotalPrice())
End Function
Enter fullscreen mode Exit fullscreen mode

Performance Comparison

For apps making frequent cross-runtime calls, this matters:

Method Latency/Call Throughput Best For
REST/HTTP 2-15ms ~500-2K/sec Loose coupling, cross-network
gRPC 0.5-3ms ~2K-10K/sec High-throughput microservices
In-process bridge (shared mem) 0.01-0.1ms ~50K-500K/sec Tight integration, real-time
In-process bridge (TCP) 0.1-1ms ~5K-50K/sec Cross-process deployment

The shared-memory bridge is 100-1000x faster than REST for individual calls. Negligible for occasional calls — transformative when your VB.NET app is doing real-time pricing or batch data processing.

Architecture Pattern: Wrapper Service Layer

My recommendation — create a VB.NET wrapper class that isolates all Java calls. The rest of your app gets a clean .NET API:

Public Class JavaPricingService
    Private _engine As PricingEngine

    Public Sub New()
        _engine = New PricingEngine()
        _engine.loadRules("pricing-rules-2026.xml")
    End Sub

    Public Function GetPrice(productId As String, qty As Integer) As Decimal
        Dim request As New PriceRequest()
        request.setProductId(productId)
        request.setQuantity(qty)
        Return CDec(_engine.calculate(request).getTotalPrice())
    End Function
End Class
Enter fullscreen mode Exit fullscreen mode

Your application code never needs to know it's talking to Java under the hood.

Mixed Teams? Same Proxies Work in C

If your team uses both VB.NET and C#, the proxy assembly is language-agnostic:

// Same Kafka example in C# — same proxy DLL
var props = new Properties();
props.put("bootstrap.servers", "kafka-broker:9092");
var producer = new KafkaProducer(props);
producer.send(new ProducerRecord(topic, "key", message));
Enter fullscreen mode Exit fullscreen mode

Generate once, use from any .NET language.

Watch Out For

  1. JVM Memory — The JVM runs inside your .NET process. Set -Xmx appropriately or you'll get mysterious OOM crashes.

  2. Thread Safety — Java objects follow Java's threading model. If the Java library isn't thread-safe, use SyncLock or per-thread instances on the VB.NET side.

  3. Classpath Issues — The #1 setup problem. Use jdeps to find transitive dependencies you're missing.

  4. Exception Translation — Java exceptions become .NET exceptions through the bridge. Catch JNBException for bridge errors, original Java types for app errors.

Getting Started

  1. Download JNBridgePro (free evaluation)
  2. Generate proxies for your Java classes
  3. Add references to your VB.NET project
  4. Write code using native VB.NET syntax
  5. Deploy — both JVM and CLR must be present on target

Works with .NET Framework and .NET Core/.NET 8/9. If you're migrating from Framework to modern .NET, your Java integration code carries over.


Have questions about VB.NET + Java integration? Drop them in the comments — I'll answer from production experience.

Top comments (0)