# JeroMQ speaks ZeroMQ without a native library

> JeroMQ is a pure Java implementation of libzmq, so a Java service can use the same socket types and wire protocol without shipping a C library. It tracks libzmq 4.1.7 and ZMTP 3.0, supports PLAIN and CURVE security, and leaves out ipc with libzmq peers, the PGM, NORM and TIPC transports, GSSAPI, and thread interruption.

**zeromq/jeromq** — JeroMQ is a pure Java implementation of the ZeroMQ messaging library, offering high-performance asynchronous messaging for distributed or concurrent applications.

- Repository: https://github.com/zeromq/jeromq
- Website: https://zeromq.org
- Stars: 2,453 · Forks: 489
- Language: Java
- License: MPL-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/zeromq-jeromq

## The same sockets, without the C library

JeroMQ is a pure Java implementation of libzmq, and the appeal is precisely that there is no native library to install. A Java service that needs ZeroMQ socket types, patterns such as publish and subscribe or push and pull, and the dealer and router routing, gets them in a jar with no platform specific build step.

The compatibility claim is concrete in the README. The library is based on libzmq 4.1.7 and implements ZMTP 3.0, the wire protocol specification, so a JeroMQ endpoint and a libzmq endpoint can talk over the network using the tcp:// protocol. inproc:// is compatible with ZeroMQ as well, and the ipc:// protocol works between JeroMQ instances, using tcp://127.0.0.1:port internally. The developer experience is described as exactly the same as with ZeroMQ and jzmq, which is the practical version of that claim for anyone porting code.

The performance figure given is 4.5 million messages of 100 bytes per second, with the README describing it as not too bad compared to native libzmq and linking to a performance page for more. That is the trade the library names for itself: not native speed, but a messaging stack you can deploy like any other Java dependency.

The repository is laid out as a multi-module project with jeromq-core, a jeromq module, a jeromq-ipcsockets module, a doc folder, scripts and a src directory, and the code is published to Maven Central under the group id org.zeromq.

## What works between Java and native peers, and what does not

The unsupported list is the most useful part of the README for an engineer choosing a transport, and it is stated without hedging.

IPC between JeroMQ and libzmq is not supported, and the reason is plain: Java does not support UNIX domain sockets. Inside the JVM, ipc:// still works between JeroMQ instances because the implementation maps it onto a loopback TCP port. If your architecture is a Java service talking to a native ZeroMQ service on the same host, you are on tcp:// or you are rewriting something.

Three transports are absent entirely, each for the same stated reason, that no Java implementation could be found: pgm://, which is the multicast transport, norm:// and tipc://. The practical effect of the missing pgm:// support is that reliable multicast is not available through this library, and if your design depends on a multicast group, that is a hard boundary rather than a configuration gap.

There is also a JVM detail in the features list. TCP keepalive count, idle and interval are known to only work on JVM 13 and later. If you deploy on an older JVM, those socket options are accepted and then do nothing, which is the kind of thing that produces a connection that survives longer than you expect.

The trade-off is coherent: keep everything in Java and you lose the exotic transports, keep the native library and you lose the pure Java deployment story. Most services need neither multicast nor IPC with a native peer, which is why this arrangement works for a lot of people.

## PLAIN and CURVE, with GSSAPI still missing

The security mechanisms listed are PLAIN and CURVE, with links to the corresponding ZeroMQ specifications. CURVE is the one that matters for a deployment where a password is not enough, since it provides encryption and a key based handshake rather than a shared secret in the clear. PLAIN is the simple username and password mechanism, useful when the transport is already protected by something else.

What is not there is GSSAPI, listed as not yet implemented. That is a real limitation for organisations whose service identity comes from Kerberos, and the wording is a status report rather than a design decision, so it may change.

Security in ZeroMQ sits at the socket level rather than in a broker, which means each endpoint decides for itself whether to require a mechanism. In a mixed deployment, one endpoint with no mechanism configured will happily accept a plaintext peer, so the policy has to be enforced on both sides and checked in configuration. The README does not document a default posture, so treat that as something to set deliberately rather than inherit.

The other structural point is worth stating plainly, because it decides the deployment: there is no broker process in this design. A JeroMQ service is a set of sockets bound to endpoints, and the routing, the queues and the delivery semantics all come from the socket pattern you choose.

## Adding JeroMQ to a Maven project

The dependency coordinates are org.zeromq with the artifact jeromq, and the README shows the block to paste into a pom.xml:

```xml
    <dependency>
      <groupId>org.zeromq</groupId>
      <artifactId>jeromq</artifactId>
      <version>0.6.0</version>
    </dependency>
```

The same block appears a second time in the documentation under a comment about the latest snapshot, with the version unchanged at 0.6.0. That is a documentation inconsistency rather than a working recipe, so treat the snapshot guidance as unreliable and resolve the version yourself from Maven Central.

If you need the snapshot repository rather than a release, the documentation adds a repository block pointing at the Sonatype OSS snapshots:

```xml
    <repositories>
      <repository>
        <id>sonatype-nexus-snapshots</id>
        <url>https://oss.sonatype.org/content/repositories/snapshots</url>
        <releases>
          <enabled>false</enabled>
        </releases>
        <snapshots>
          <enabled>true</enabled>
        </snapshots>
       </repository>
    </repositories>
```

For Ant users, the README shows a one-liner to generate an Ant build file from the Maven one:

```bash
mvn ant:ant
```

Beyond the build, the documentation points at two places for learning the API. The JeroMQ translations of the zguide examples live in the test tree of the core module, and they are described as a good reference for recommended usage. There is also a doc folder in the repository with assorted how to do X guides, and published Javadocs are available for the API itself.

## A reply socket bound to a TCP port

The worked example is a small server that prints what it receives and answers with a greeting. It shows the three objects that matter: a ZContext that owns the sockets and must be closed, a socket created with a SocketType, and a bind to a TCP endpoint.

```java
import org.zeromq.SocketType;
import org.zeromq.ZMQ;
import org.zeromq.ZContext;

public class hwserver
{
    public static void main(String[] args) throws Exception
    {
        try (ZContext context = new ZContext()) {
            // Socket to talk to clients
            ZMQ.Socket socket = context.createSocket(SocketType.REP);
            socket.bind("tcp://*:5555");

            while (!Thread.currentThread().isInterrupted()) {
                // Block until a message is received
                byte[] reply = socket.recv(0);

                // Print the message
                System.out.println(
                    "Received: [" + new String(reply, ZMQ.CHARSET) + "]"
                );

                // Send a response
                String response = "Hello, world!";
                socket.send(response.getBytes(ZMQ.CHARSET), 0);
            }
        }
    }
}
```

Three details in that code deserve attention. The context is used in a try with resources block, so sockets are released when the scope ends, which matters because a socket left open holds its endpoint. The receive call passes 0, which means block indefinitely, and the loop condition checks Thread.currentThread().isInterrupted(), which is the sanctioned way to leave that loop.

And that last point is where the library's sharpest limitation sits, which is the subject of the next section. The binding string tcp://*:5555 is the wildcard interface on port 5555, the same port the zguide examples use.

## The library is not Thread.interrupt safe

The unsupported list includes a single entry about threads rather than about protocols, and it is easy to read past. Interrupting threads is still unsupported, and the README states it plainly: the library is NOT Thread.interrupt safe.

That has a concrete consequence for the example above. The loop appears to be interruptible, because it checks the interrupt flag, but a thread blocked inside a receive call is not guaranteed to return when another thread interrupts it. In practice this means the shutdown path of a service that blocks on a socket cannot rely on interruption alone, and a supervisor that expects a blocked socket to unblock on interrupt will find the thread sitting there until the process is stopped by other means.

The pattern that follows from the API is to keep the blocking call short and to make the blocking itself the shutdown signal, for example by sending a control message or by closing the socket, rather than by interrupting the thread. The documentation in the doc folder exists for exactly this kind of question, and the examples in the test tree show the recommended usage for each socket type.

The second limitation is performance relative to the native library. 4.5 million 100 byte messages per second is a respectable number for a JVM implementation, and the README is upfront that it is not native libzmq speed. If your workload is dominated by message counts rather than by payloads, that gap is the one you will feel.

## MPL-2.0, no release tags, and a living master branch

The licence is the Mozilla Public License 2.0, and the README states that free use is granted under its terms, with the details in the LICENSE file. Source files are copyright the contributors named in the AUTHORS file, dated 2007 to 2024. MPL is a file level copyleft licence, which is a reasonable choice for a library that others embed: modifications to the library's own files stay open, while an application that merely depends on it is not forced to publish its own code.

On maintenance, the repository is not archived and the last push was on 2026-10-16, so work is current, but there are no GitHub releases, so there is no tag to point at and no release notes to skim. The version you will see referenced in the documentation is 0.6.0, and the artifact is on Maven Central under the same coordinates, which means the practical upgrade path is watching the Central version rather than a release page.

The project runs on CircleCI, with a SonarCloud quality gate badge and a Coveralls coverage badge, and it welcomes contributions through a CONTRIBUTING.md that describes the contribution process and useful development tasks. There is also a CHANGELOG.md at the top level, which is where a reader should look first to see what changed in a given release, given that the release history itself is not published as tags.

## Conclusion

JeroMQ suits Java teams that want ZeroMQ socket semantics and peer to peer messaging without a native dependency, especially where a container image or a restricted runtime makes native libraries awkward. It is the wrong choice if you need IPC transports against libzmq peers, GSSAPI, PGM multicast, or code that relies on Thread.interrupt to stop a blocked socket. Verify first that the peers you must talk to can use tcp:// or inproc://, that your JVM is version 13 or later if you rely on TCP keepalive settings, and that the jar you pull from Maven Central matches the libzmq behaviour the other end of the connection expects.

## FAQ

### What is JeroMQ and which version of libzmq is it based on?

JeroMQ is a pure Java implementation of libzmq based on libzmq 4.1.7, implementing the ZMTP 3.0 wire protocol. The developer experience is described as exactly the same as with ZeroMQ and jzmq, and it is published to Maven Central as org.zeromq with the artifact jeromq.

### Can a JeroMQ application talk to a native libzmq application?

Yes, over the tcp:// protocol, and inproc:// is compatible with ZeroMQ as well. The ipc:// protocol works only between JeroMQ instances, since it uses tcp://127.0.0.1:port internally, and Java does not support UNIX domain sockets.

### Which transports and security mechanisms does JeroMQ not support?

The pgm://, norm:// and tipc:// protocols are not implemented because no Java implementation could be found, and the GSSAPI mechanism is not yet implemented. The supported security mechanisms are PLAIN and CURVE.

### How do I add JeroMQ to a Maven project?

Add a dependency with groupId org.zeromq, artifactId jeromq and a version, in the documentation shown as 0.6.0. For Ant users the README shows mvn ant:ant to generate an Ant build file from the pom.xml.

### Is JeroMQ still maintained and how is it licensed?

The repository is not archived and the last push was on 2026-10-16, though it publishes no GitHub releases, so the CHANGELOG.md at the top level is the record of changes. It is licensed under the Mozilla Public License 2.0, with source files copyright the contributors in the AUTHORS file.

## Sources

- [Issues](https://github.com/zeromq/jeromq/issues)
- [License: MPL-2.0](https://github.com/zeromq/jeromq/blob/master/LICENSE)
- [Project website](https://zeromq.org)
- [README](https://github.com/zeromq/jeromq/blob/master/README.md)
- [zeromq/jeromq on GitHub](https://github.com/zeromq/jeromq)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/zeromq-jeromq
