Java remote debugging stymied by connection refused on local network

I am trying to setup remote Java debugging between two machines running macOS (15.6 and 26).

I am able to get the Java program to listen on a socket. However, I can connect to that socket only from the same machine, not from another machine on my local network. I use nc to test the connection. It reports Connection refused when trying to connect from the other machine.

This issue sounds like it could be caused by the Java program lacking Local Network system permission. I am familiar with that issue arising when a program attempts to connect to a port on the local network. In that case, a dialog is displayed and System Settings can be used to grant Local Network permission to the client program. I don't know whether the same permission is required on the program that is receiving client requests. If it is, then I don't know how to grant that permission. There is no dialog, and System Settings does not provide any obvious way to grant permission to a program that I specify.

Note that a Java application is a program run by the java command, not a bundled application. The java command contains a hard-wired Info.plist which, annoyingly, requests permission to use the microphone, but not Local Network access.

Answered by jaikiran in 854008022

I configure Java with: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

Based on what you note, the issue you are running into doesn't look related to the recent Local Network Privacy changes that are enforced in macos. Instead it just looks like an issue related to which interface the socket (listening on 5005) is bound to.

Starting Java 9, the instruction "address=5005" tells the JDK to bind to localhost if no specific host (like in this case) is specified in the value for "address". That's noted in the release note here https://www.oracle.com/java/technologies/javase/9-all-relnotes.html#JDK-8041435.

Based on this above output you pasted, that's what appears to be going on here - the JVM is listening on a socket bound to localhost:

nc on the same host says:

Mac-mini:13 alan$ nc -v localhost 5005 Connection to localhost port 5005 [tcp/avt-profile-2] succeeded!

These following documents have the details about how to configure the "address" option:

https://docs.oracle.com/en/java/javase/17/docs/specs/jpda/conninv.html#oracle-vm-invocation-options

https://docs.oracle.com/en/java/javase/17/docs/specs/jpda/conninv.html#transports

Specifically, the documentation states:

Socket transport addresses have the format "<host>:<port>" where <host> is the host name or the IP address (may be enclosed in square brackets) and <port> is the socket port number to attach to or listen on. If <host> is empty, the local loopback address is used. If <host> equals "*" in contexts where a server is waiting for a client to attach, the server listens on all network interfaces.

Hello @cbfiddle,

I am trying to setup remote Java debugging between two machines running macOS (15.6 and 26). I am able to get the Java program to listen on a socket.

What exact option do you use to launch the java application with?

I use nc to test the connection. It reports Connection refused when trying to connect from the other machine.

Is there any firewall involved on either of these systems?

The java command contains a hard-wired Info.plist which, annoyingly, requests permission to use the microphone, but not Local Network access.

As far as I know, there's no permission id that can be used to request/grant Local network access to applications. It has to be explicitly granted whenever the macos system shows up the popup.

I’m gonna start by dropping a link to TN3179 Understanding local network privacy, because it contains vital backstory.

As explained in TN3179, tools run from Terminal get implicit local network access. Thus I see two possibilities:

  • Java is doing something weird to break that association.
  • There’s something else afoot.

I recommend that you rule out the second possibility before digging into Java itself. To do that, run nc from Terminal:

% nc -l 12345

replacing 12345 with your port number, and then try to connect to it from your other Mac:

% nc -v guy-smily.local. 12345

replacing guy-smily.local. with the server’s local DNS name or IP address.

What do you get?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I configure Java with: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

Java says: Listening for transport dt_socket at address: 5005

nc from the other machine says:

nc -v mac-mini.local 5005
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused
nc: connectx to mac-mini.local port 5005 (tcp) failed: Connection refused

nc on the same host says:

Mac-mini:13 alan$ nc -v localhost 5005
Connection to localhost port 5005 [tcp/avt-profile-2] succeeded!
Accepted Answer

I configure Java with: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

Based on what you note, the issue you are running into doesn't look related to the recent Local Network Privacy changes that are enforced in macos. Instead it just looks like an issue related to which interface the socket (listening on 5005) is bound to.

Starting Java 9, the instruction "address=5005" tells the JDK to bind to localhost if no specific host (like in this case) is specified in the value for "address". That's noted in the release note here https://www.oracle.com/java/technologies/javase/9-all-relnotes.html#JDK-8041435.

Based on this above output you pasted, that's what appears to be going on here - the JVM is listening on a socket bound to localhost:

nc on the same host says:

Mac-mini:13 alan$ nc -v localhost 5005 Connection to localhost port 5005 [tcp/avt-profile-2] succeeded!

These following documents have the details about how to configure the "address" option:

https://docs.oracle.com/en/java/javase/17/docs/specs/jpda/conninv.html#oracle-vm-invocation-options

https://docs.oracle.com/en/java/javase/17/docs/specs/jpda/conninv.html#transports

Specifically, the documentation states:

Socket transport addresses have the format "<host>:<port>" where <host> is the host name or the IP address (may be enclosed in square brackets) and <port> is the socket port number to attach to or listen on. If <host> is empty, the local loopback address is used. If <host> equals "*" in contexts where a server is waiting for a client to attach, the server listens on all network interfaces.

Thank you! That subtle change makes the difference.

Java remote debugging stymied by connection refused on local network
 
 
Q