JmDNS, a multicast DNS service registry for Java
Official home of the JmDNS library
At a glance
- What is it?
- JmDNS is the Java implementation of multicast DNS that lets devices on a local network find and register services without a directory server, and it interoperates with Apple Bonjour. The catch is scope: it is a LAN-only mechanism, not a service discovery system for a datacenter.
- Who is it for?
- JmDNS fits Java applications on a shared local network that need to publish or locate a service such as a printer, a media server or a device UI without configuring addresses by hand, and it is a reasonable choice for a desktop or IoT side project that already depends on Maven. It does not fit services that must be reachable across subnets, from the internet, or by a client that speaks only DNS-SD over unicast DNS, because the mechanism is multicast on the local segment.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Service discovery that needs no server at all
JmDNS exists to remove one piece of setup from a network: the address book. Instead of maintaining a registry of which machine offers which service, a JmDNS instance announces and hears announcements on the local link. The library is described in the project README as a Java implementation of multicast DNS that supports both service discovery and service registration, and it states that it is fully interoperable with Apple's Bonjour.
That last point decides who should look at it. If the machines on your network already run Bonjour, or you want an iOS or macOS client to see a service published from a JVM, JmDNS speaks the same protocol and the same record format. Interoperability here is a documented claim about protocol compatibility rather than a benchmark, but it is the reason a Java service can be discovered by a tool outside the JVM world at all.
The intended users are therefore narrow and specific: developers of JVM applications that talk to peers or expose services on a local network. Printers, media servers, device configuration screens, test harnesses that need to find a running instance. If you are looking for something that resolves service names across a corporate network with many subnets, this is the wrong shape of tool, and no amount of configuration will change the fact that multicast does not cross a router without help.
Two operations, one JmDNS instance
The library exposes two halves, and the sample code in the README makes the shape of each one concrete.
Registration is the shortest path. You create a JmDNS instance bound to a local address, build a ServiceInfo describing the service type, name, port and TXT properties, and register it. The instance in the sample is created from the local host address.
try {
// Create a JmDNS instance
JmDNS jmdns = JmDNS.create(InetAddress.getLocalHost());
// Register a service
ServiceInfo serviceInfo = ServiceInfo.create("_http._tcp.local.", "example", 1234, "path=index.html");
jmdns.registerService(serviceInfo);
// Wait a bit
Thread.sleep(25000);
// Unregister all services
jmdns.unregisterAllServices();
} catch (IOException e) {
System.out.println(e.getMessage());
}Four things are worth reading out of that snippet. The service type follows the DNS-SD convention, here _http._tcp.local. The instance name is the second argument, example. The port is a plain integer, 1234 here. The trailing string is the TXT record, a key=value pair that the sample sets to path=index.html and that a client can read to learn the path of the resource without connecting first.
The last two calls are the ones production code forgets. The thread sleeps for 25 seconds to give the announcement time to propagate, then unregisters all services so the record goes away on a clean shutdown. Skip that unregister step and other devices keep a stale entry pointing at an address that no longer answers, which is the classic local-discovery failure mode: the phone still shows the printer that was unplugged an hour ago.
Discovery works through a listener, not a polling loop
The other half is the reverse direction, and it uses a callback object rather than a query you run yourself. A listener is attached for a service type and the library calls back when something appears, disappears, or has been resolved.
private static class SampleListener implements ServiceListener {
@Override
public void serviceAdded(ServiceEvent event) {
System.out.println("Service added: " + event.getInfo());
}
@Override
public void serviceRemoved(ServiceEvent event) {
System.out.println("Service removed: " + event.getInfo());
}
@Override
public void serviceResolved(ServiceEvent event) {
System.out.println("Service resolved: " + event.getInfo());
}
}Three callbacks rather than one tells you a lot about the protocol. Added means an announcement arrived. Resolved means the full record, including address and port, has been fetched. Removed means the service went away. A client that treats added as usable will connect too early, before resolution, and a client that ignores removed will keep trying a service that has already gone. The distinction between an announcement and a resolved record is the part that trips up first-time users of multicast DNS, because with plain DNS a query returns a final answer in one step.
The sample then registers the listener against a type and a concrete service instance.
JmDNS jmdns = JmDNS.create(InetAddress.getLocalHost());
// Add a service listener
jmdns.addServiceListener("_http._tcp.local.", new SampleListener());Note the argument order. The listener is scoped to one service type, and it fires for every instance of that type it hears, so a device that publishes three printers produces three resolved events with different names. The sample waits 30 seconds and then exits, which is fine for a demonstration and tells you nothing about the lifetime of the JmDNS instance itself. The README does not document how long a JmDNS object should be kept alive, nor how it is closed, so that part of your integration is something the source has to answer for you.
Maven coordinates and a build you do not have to run
There is no installation guide in the README because there is nothing to install. JmDNS is published to Maven Central under the coordinates org.jmdns:jmdns, which is what the version badge in the README points at, and the repository is a standard Maven project with a pom.xml at its root and a GitHub Actions workflow for Maven builds. Adding the dependency to an existing pom is the whole setup step for a Maven-based project.
The repository layout is worth a glance before you commit. Besides the pom.xml there is a src/ directory holding the library sources, a CHANGELOG.txt at the top level, a NOTICE.txt file for the Apache attribution requirements, and devdocs/ for developer documentation. The presence of a separate devdocs directory next to the small README is a signal about where the real detail lives, since the README itself is only a couple of paragraphs plus two samples.
There is also a .classpath and .project file at the root, which are Eclipse project metadata. That does not mean Eclipse is required, and it does not tell you the project is maintained in Eclipse. It tells you that somebody at some point committed IDE state, which is worth knowing before you complain about it. The CHANGELOG.txt, by contrast, is where you should look for what changed between the versions, since the README says nothing about upgrade behaviour.
Version 3.6.x and the pace of releases
The release record shows a steady line of point releases: v3.6.2 in August 2025, v3.6.3 in December 2025, and v3.6.4 in October 2026. The last push to the repository was on 2026-10-10, the same day as the v3.6.4 release. Nothing about that pattern suggests a rewrite in progress, and the versioning scheme gives you a stable artifact to depend on.
For an adopter the useful question is what changes between point releases. The README does not document a compatibility policy, and the CHANGELOG.txt in the repository is the place to answer that. A library like this sits in the awkward middle ground of dependencies: it is small, it has few transitive requirements, and it touches a piece of infrastructure that is easy to notice when it fails. Because it runs inside your JVM, a version bump is cheap, but a behavioral change in announcement timing or record parsing is invisible in the diff of your own code.
Apache-2.0 governs the code. That licence permits use in proprietary and closed-source products, requires the notice file to be carried along, and asks that modifications be marked. It also brings the patent grant and the termination clause, which is why it dominates enterprise Java procurement. Nothing in the licence obliges you to open-source your application, and nothing about the multicast traffic JmDNS generates is constrained by it.
What multicast DNS will not do for you
The honest limitation is the network layer, and it is not a tuning problem. Multicast DNS resolves names on the local link. A device on a different subnet, behind a router that filters multicast, or on a VPN segment cannot see your announcements, and neither can you see theirs. No configuration in JmDNS changes that. If your deployment involves a laptop and a server in different rooms across separate subnets, the library will appear to work and simply never find anything.
The second limitation is protocol coverage. Interoperability is with Bonjour and other mDNS implementations on the same link. A client that looks up services through unicast DNS-SD in the DNS-SD domain, or a client that has no multicast DNS support at all, is outside what JmDNS speaks. The library's own answer to that is the spin-off fonts of nothing: it does not offer a bridge or a reflector in what the README describes.
The third is operational visibility. The samples print to standard output, and the README documents nothing about logging configuration, metrics, or what a JmDNS instance does when the network changes underneath it. If the service you depend on is discovered over multicast, you need your own health signal for it, because from the outside, a device that stopped announcing and a device that was never on the network look identical from the client's side.
One more constraint deserves a mention for anyone running this in a container or a locked-down enterprise network: multicast requires that the host and the network permit it. Containers with restrictive bridge networking and VLANs that drop unknown multicast traffic will both break the mechanism in ways that produce silence rather than an error.
Where a different approach fits better
The real alternative is not another multicast DNS library, it is giving up on local-network discovery. A service registry backed by a plain HTTP or DNS endpoint, where clients are configured with a base URL, does not depend on the network permitting multicast and works across subnets. Many production systems made the same call for exactly the reasons above: a configuration step is cheaper than debugging a silent multicast failure. If your service list is small and known at deploy time, hardcoded addresses and a config file beat an announcement protocol.
When local discovery is genuinely the right answer, the alternative inside the protocol space is to rely on the platform's own implementation rather than a JVM library, for example using Bonjour on Apple platforms, which gives the same records to the same listeners without a Java dependency in the mix. The difference in approach is that a JVM library gives you the same records inside your process, under your own control and on any platform the JVM runs on, at the cost of owning the dependency and the operational blind spot that comes with it.
There is a third framing worth stating plainly. JmDNS is best treated as a convenience for adjacent devices, not as a service mesh. If what you actually need is discovery with health checks, retries and versioning across a fleet, that is a different category of software, and JmDNS will not grow into it.
Editorial conclusion
JmDNS fits Java applications on a shared local network that need to publish or locate a service such as a printer, a media server or a device UI without configuring addresses by hand, and it is a reasonable choice for a desktop or IoT side project that already depends on Maven. It does not fit services that must be reachable across subnets, from the internet, or by a client that speaks only DNS-SD over unicast DNS, because the mechanism is multicast on the local segment. Before adopting, verify that the devices that need to discover each other sit on the same broadcast domain, confirm that your network permits multicast traffic on the port JmDNS binds, and read the CHANGELOG.txt in the repository to see how the 3.6.x line has changed the API between releases.
Frequently asked questions
How do I add JmDNS to a Maven project?
The library is published to Maven Central under the coordinates org.jmdns:jmdns, which is the artifact the version badge in the README points at. Add that dependency to your pom.xml and use the javax.jmdns package.
How do I register a service with JmDNS in Java?
Create a JmDNS instance, build a ServiceInfo with ServiceInfo.create passing the service type, instance name, port and a TXT string, then call registerService on the instance. The README sample calls unregisterAllServices before exiting so the record does not linger.
Why does my JmDNS service discovery find nothing?
The most common causes are network level rather than code level. Multicast DNS resolves on the local link, so devices on different subnets or behind a router that filters multicast will never see each other, and containers or VLANs that drop multicast traffic fail silently.
Is JmDNS compatible with Apple Bonjour?
Yes. The project documentation states that the implementation is fully interoperable with Apple's Bonjour, which is what allows a service published from Java to be discovered by Bonjour clients on the same network.
Can I use JmDNS in a commercial application?
The library is licensed under the Apache License Version 2.0, which permits use in proprietary products provided you carry the notice file and mark any modifications. The attribution notice file in the repository is NOTICE.txt.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jmdns-jmdns)Was this useful?