Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat= Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

1. Overview

In this tutorial, we’ll see how to use the Java Native Access library (JNA for short) to access native libraries without writing any JNI (Java Native Interface) code.

2. Why JNA?

For many years, Java and other JVM-based languages have, to a large extent, fulfilled its “write once, run everywhere” motto. However, sometimes we need to use native code to implement some functionality:

  • Reusing legacy code written in C/C++ or any other language able to create native code
  • Accessing system-specific functionality not available in the standard Java runtime
  • Optimizing speed and/or memory usage for specific sections of a given application.

Initially, this kind of requirement meant we’d have to resort do JNI – Java Native Interface. While effective, this approach has its drawbacks and was generally avoided due to a few issues:

  • Requires developers to write C/C++ “glue code” to bridge Java and native code
  • Requires a full compile and link toolchain available for every target system
  • Marshaling and unmarshalling values to and from the JVM is a tedious and error-prone task
  • Legal and support concerns when mixing Java and native libraries

JNA came to solve most of the complexity associated with using JNI. In particular, there’s no need to create any JNI code to use native code located in dynamic libraries, which makes the whole process much easier.

Of course, there are some trade-offs:

  • We can’t directly use static libraries
  • Slower when compared to handcrafted JNI code

For most applications, though, JNA’s simplicity benefits far outweigh those disadvantages. As such, it is fair to say that, unless we have very specific requirements, JNA today is probably the best available choice to access native code from Java – or any other JVM-based language, by the way.

3. JNA Project Setup

The first thing we have to do to use JNA is to add its dependencies to our project’s pom.xml:

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.6.0</version>
</dependency>

The latest version of jna-platform can be downloaded from Maven Central.

4. Using JNA

Using JNA is a two-step process:

  • First, we create a Java interface that extends JNA’s Library interface to describe the methods and types used when calling the target native code
  • Next, we pass this interface to JNA which returns a concrete implementation of this interface that we use to invoke native methods

4.1. Calling Methods from the C Standard Library

For our first example, let’s use JNA to call the cosh function from the standard C library, which is available in most systems. This method takes a double argument and computes its hyperbolic cosine. A-C program can use this function just by including the <math.h> header file:

#include <math.h>
#include <stdio.h>
int main(int argc, char** argv) {
    double v = cosh(0.0);
    printf("Result: %f\n", v);
}

Let’s create the Java interface needed to call this method:

public interface CMath extends Library { 
    double cosh(double value);
}

Next, we use JNA’s Native class to create a concrete implementation of this interface so we can call our API:

CMath lib = Native.load(Platform.isWindows()?"msvcrt":"c", CMath.class);
double result = lib.cosh(0);

The really interesting part here is the call to the load() method. It takes two arguments: the dynamic library name and a Java interface describing the methods that we’ll use. It returns a concrete implementation of this interface, allowing us to call any of its methods.

Now, dynamic library names are usually system-dependent, and C standard library is no exception: libc.so in most Linux-based systems, but msvcrt.dll in Windows. This is why we’ve used the Platform helper class, included in JNA, to check which platform we’re running in and select the proper library name.

Notice that we don’t have to add the .so or .dll extension, as they’re implied. Also, for Linux-based systems, we don’t need to specify the “lib” prefix that is standard for shared libraries.

Since dynamic libraries behave like Singletons from a Java perspective, a common practice is to declare an INSTANCE field as part of the interface declaration:

public interface CMath extends Library {
    CMath INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c", CMath.class);
    double cosh(double value);
}

4.2. Basic Types Mapping

In our initial example, the called method only used primitive types as both its argument and return value. JNA handles those cases automatically, usually using their natural Java counterparts when mapping from C types:

  • char => byte
  • short => short
  • wchar_t => char
  • int => int
  • long => com.sun.jna.NativeLong
  • long long => long
  • float => float
  • double => double
  • char * => String

A mapping that might look odd is the one used for the native long type. This is because, in C/C++, the long type may represent a 32- or 64-bit value, depending on whether we’re running on a 32- or 64-bit system.

To address this issue, JNA provides the NativeLong type, which uses the proper type depending on the system’s architecture.

4.3. Structures and Unions

Another common scenario is dealing with native code APIs that expect a pointer to some struct or union type. When creating the Java interface to access it, the corresponding argument or return value must be a Java type that extends Structure or Union, respectively.

For instance, given this C struct:

struct foo_t {
    int field1;
    int field2;
    char *field3;
};

Its Java peer class would be:

@FieldOrder({"field1","field2","field3"})
public class FooType extends Structure {
    int field1;
    int field2;
    String field3;
};

JNA requires the @FieldOrder annotation so it can properly serialize data into a memory buffer before using it as an argument to the target method.

Alternatively, we can override the getFieldOrder() method for the same effect. When targeting a single architecture/platform, the former method is generally good enough. We can use the latter to deal with alignment issues across platforms, that sometimes require adding some extra padding fields.

Unions work similarly, except for a few points:

  • No need to use a @FieldOrder annotation or implement getFieldOrder()
  • We have to call setType() before calling the native method

Let’s see how to do it with a simple example:

public class MyUnion extends Union {
    public String foo;
    public double bar;
};

Now, let’s use MyUnion with a hypothetical library:

MyUnion u = new MyUnion();
u.foo = "test";
u.setType(String.class);
lib.some_method(u);

If both foo and bar where of the same type, we’d have to use the field’s name instead:

u.foo = "test";
u.setType("foo");
lib.some_method(u);

4.4. Using Pointers

JNA offers a Pointer abstraction that helps to deal with APIs declared with untyped pointer – typically a void *. This class offers methods that allow read and write access to the underlying native memory buffer, which has obvious risks.

Before start using this class, we must be sure we clearly understand who “owns” the referenced memory at each time. Failing to do so will likely produce hard to debug errors related to memory leaks and/or invalid accesses.

Assuming we know what we’re doing (as always), let’s see how we can use the well-known malloc() and free() functions with JNA, used to allocate and release a memory buffer. First, let’s again create our wrapper interface:

public interface StdC extends Library {
    StdC INSTANCE = // ... instance creation omitted
    Pointer malloc(long n);
    void free(Pointer p);
}

Now, let’s use it to allocate a buffer and play with it:

StdC lib = StdC.INSTANCE;
Pointer p = lib.malloc(1024);
p.setMemory(0l, 1024l, (byte) 0);
lib.free(p);

The setMemory() method just fills the underlying buffer with a constant byte value (zero, in this case). Notice that the Pointer instance has no idea to what it is pointing to, much less its size. This means that we can quite easily corrupt our heap using its methods.

We’ll see later how we can mitigate such errors using JNA’s crash protection feature.

4.5. Handling Errors

Old versions of the standard C library used the global errno variable to store the reason a particular call failed. For instance, this is how a typical open() call would use this global variable in C:

int fd = open("some path", O_RDONLY);
if (fd < 0) {
    printf("Open failed: errno=%d\n", errno);
    exit(1);
}

Of course, in modern multi-threaded programs this code would not work, right? Well, thanks to C’s preprocessor, developers can still write code like this and it will work just fine. It turns out that nowadays, errno is a macro that expands to a function call:

// ... excerpt from bits/errno.h on Linux
#define errno (*__errno_location ())

// ... excerpt from <errno.h> from Visual Studio
#define errno (*_errno())

Now, this approach works fine when compiling source code, but there’s no such thing when using JNA. We could declare the expanded function in our wrapper interface and call it explicitly, but JNA offers a better alternative: LastErrorException.

Any method declared in wrapper interfaces with throws LastErrorException will automatically include a check for an error after a native call. If it reports an error, JNA will throw a LastErrorException, which includes the original error code.

Let’s add a couple of methods to the StdC wrapper interface we’ve used before to show this feature in action:

public interface StdC extends Library {
    // ... other methods omitted
    int open(String path, int flags) throws LastErrorException;
    int close(int fd) throws LastErrorException;
}

Now, we can use open() in a try/catch clause:

StdC lib = StdC.INSTANCE;
int fd = 0;
try {
    fd = lib.open("/some/path",0);
    // ... use fd
}
catch (LastErrorException err) {
    // ... error handling
}
finally {
    if (fd > 0) {
       lib.close(fd);
    }
}

In the catch block, we can use LastErrorException.getErrorCode() to get the original errno value and use it as part of the error handling logic.

4.6. Handling Access Violations

As mentioned before, JNA does not protect us from misusing a given API, especially when dealing with memory buffers passed back and forth native code. In normal situations, such errors result in an access violation and terminate the JVM.

JNA supports, to some extent, a method that allows Java code to handle access violation errors. There are two ways to activate it:

  • Setting the jna.protected system property to true
  • Calling Native.setProtected(true)

Once we’ve activated this protected mode, JNA will catch access violation errors that would normally result in a crash and throw a java.lang.Error exception. We can verify that this works using a Pointer initialized with an invalid address and trying to write some data to it:

Native.setProtected(true);
Pointer p = new Pointer(0l);
try {
    p.setMemory(0, 100*1024, (byte) 0);
}
catch (Error err) {
    // ... error handling omitted
}

However, as the documentation states, this feature should only be used for debugging/development purposes.

5. Conclusion

In this article, we’ve shown how to use JNA to access native code easily when compared to JNI.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat = Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Course – LS – NPI (cat=Java)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)