Description

I have 2 freshly installed MacBooks.
They have addresses 192.168.1.2 and 192.168.1.3 in my Wi-Fi network.
Both of them are turned on.

I use the second laptop (with 192.168.1.3)
I launch a local Java program that I want to profile (under JVM 1.7).
I launch a local VisualVM after that (under same JVM 1.7).

VisualVM attaches to program JVM, bur fails to show CPU graph.
Instead of CPU I graph it says "Not supported for this JVM".

When open VisualVM log I can see:
=============================================
INFO [com.sun.tools.visualvm.jmx.impl.JmxModelImpl]: connect(6984)
java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
Caused: java.rmi.ConnectException: Connection refused to host: 192.168.1.2; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:128)
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2370)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:296)
at com.sun.tools.visualvm.jmx.impl.JmxModelImpl$ProxyClient.tryConnect(JmxModelImpl.java:476)
=============================================

Clearly, a laptop on which I am running the program + Visual VM, both locally, which has IP 192.168.1.3 tries to connect to its neighbour with IP 192.168.1.2 .

If I turn off Wi-Fi on laptop with IP 192.168.1.3, and re-run the program + JVM...
...suddenly it works (I can see CPU graph)

If I turn on Wi-Fi on back on laptop with IP 192.168.1.3, then the problem is back (no CPU graph, I see it's attempting to connect to neighbour 192.168.1.2).

Now, if I run a Java program on first laptop with IP 192.168.1.2, I can see the CPU grap when on Visual VM.

Observation:

telemetry and memory profiling works with "localhost" when attaching to local JVM

CPU profiling / sampling doesn't work when attaching to local JVM (it uses "hostname" to resolve local host)

Why is it happening:

When Mac OS X is installed, the hostname is set to default (regardless of System Preferences > Sharing > Computer Name):

$ hostname
macbook

So "ping `hostmame`" will actually (quite often) ping neighbors on Wi-Fi.
Sometimes it will resolve just fine to its own (external) IP.

Conclusion:
Apparently, different parts of VisualVM (CPU vs Memory and telemetry) use different ways to resolve "local host".

Fix:
I believe it is preferred to skip host resolution for local host (use loopback IP instead).

Workaround:
If you ran into a similar problem, try changing your "host name".
Here is how to change host name on Mac OS X

$ sudo scutil --set HostName NEW_HOSTNAME

Then reboot.

Activity

VisualVM uses different technologies (some of them are using TCP/IP some are not). This is the reason, why some data are always available. For local application monitoring, VisualVM does no host resolution. The problem seems to be in JDK. Can you try the same scenario with JDK 6?

thurka
added a comment - 31/Jan/13 10:16 AM VisualVM uses different technologies (some of them are using TCP/IP some are not). This is the reason, why some data are always available. For local application monitoring, VisualVM does no host resolution. The problem seems to be in JDK. Can you try the same scenario with JDK 6?

Unfortunately I don't have the setup to check it with JDK6 (it was a long time ago).

You are saying:
> For local application monitoring, VisualVM does no host resolution.

I could be wrong, but I have an observation that tells the opposite.

By some means its is affected by host name clash.
It does host resolution for local applications, otherwise it would not connect to external IP like 192.168.1.3 (instead of using loopback address 127.0.0.1).

It is probably done implicitly by resolving "localhost" IP from VisualVM code, but then it goes wrong deeper in JDK code and could be a JDK bug as you say.

However it doesn't mean that it could not be (or should not be) fixed in VisualVM code.
Why not just use loopback addresses like 127.0.0.1 instead of "localhost"? (I am not sure that this will work, just guessing)

oshyshko
added a comment - 31/Jan/13 11:00 AM - edited Unfortunately I don't have the setup to check it with JDK6 (it was a long time ago).
You are saying:
> For local application monitoring, VisualVM does no host resolution.
I could be wrong, but I have an observation that tells the opposite.
By some means its is affected by host name clash.
It does host resolution for local applications, otherwise it would not connect to external IP like 192.168.1.3 (instead of using loopback address 127.0.0.1).
It is probably done implicitly by resolving "localhost" IP from VisualVM code, but then it goes wrong deeper in JDK code and could be a JDK bug as you say.
However it doesn't mean that it could not be (or should not be) fixed in VisualVM code.
Why not just use loopback addresses like 127.0.0.1 instead of "localhost"? (I am not sure that this will work, just guessing)

thurka
added a comment - 31/Jan/13 12:40 PM If you still have those two MacBooks running Mac OS X 10.8.2, you can test it with JDK 6.
For local connection VisualVM uses PID to identify the monitoring process. The rest is done by JDK, so I still believe that the problem is in JDK and not in VisualVM.