Why does java rmi keep connecting to 127.0.1.1. When ip is 192.168.X.X?
Asked Answered
G

2

7

I have a java rmi application i simply do:

Client:

Registry registry = LocateRegistry.getRegistry("localhost");
costApi = (CostApi) registry.lookup("server.CostApi");

Everything works fine when I host the server at localhost. When I start the same program at another machine withing the local network, at 192.168.x.x and change to:

Client:

Registry registry = LocateRegistry.getRegistry("192.168.x.x");
costApi = (CostApi) registry.lookup("server.CostApi");

it does not work anymore and it fails with a very strange error:

java.rmi.ConnectException: Connection refused to host: 127.0.1.1; 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:129)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
    at com.sun.proxy.$Proxy0.dataCost(Unknown Source)
    at billing.data.DataBiller.performBilling(DataBiller.java:57)
    at billing.data.DataBiller.consumeMessage(DataBiller.java:46)
    at general.templates.RabbitWorker.run(RabbitWorker.java:124)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)

I'm not even trying to connect to 127.0.1.1 but to 192.168.x.x, how do I solve this? I prefer to use java code only and not modify my machine with config files. I'm using linux

Gram answered 5/5, 2014 at 17:54 Comment(4)
Your /etc/hosts file is wrong.Paste
Did you try updating your hosts file with a specific hostname, and then past that hostname to getRegistry instead of the IP address?Regain
Yes I tried that and it did not work. Right now 127.0.1.1 is my username of the computer and I also changed that to 192.168.x.xGram
The way RMI works you first connect to the registry and ask it for the address of the object you're interested in, then connect to the address the registry gave you in order to talk to the target object. You're successfully connecting to the registry on 192.168.x.x but the registry has given you 127.0.1.1 as the address of the target object.Downward
B
11

This is usually caused by a misconfiguration. Check your /etc/hosts file to ensure that:

  • localhost maps to 127.0.0.1
  • your real hostname maps to your real host address

Some Linux distributions are known to have this back to front.

If the problem persists, try setting java.rmi.server.hostname at the server to the IP address the client should use when executing remote method calls. It needs to be set before you export any remote objects, including the Registry.

The problem is caused by the IP address embedded in the stub, which ultimately comes from something like InetAddress.getLocalAddress(), which is fallible as above. It is overridden by java.rmi.server.hostname.

This is item A.1 in the FMI FAQ, but note that the item is mistitled. It doesn't happen during lookup(), it happens when you call a remote method on the resulting stub.

Bezoar answered 6/5, 2014 at 3:1 Comment(6)
Can you explain this: your real hostname maps to your real host address. I have two entities under the ipv4 configuarain in /etc/hosts 127.0.0.1 localhost 127.0.1.1 my-username Is this right? "Some Linux distributions are known to have this back to front." is this what i have? I tried to change 127.0.1.1 to my 192.168.x.x address and it did not work:/Gram
If that's your correct IP address it should have worked.Bezoar
/etc/hosts certainly does not map my hostname to my IP address. As this is a laptop, it switches IP addresses on a regular bases, and /etc/hosts is supposed to be a static configuration file. If RMI depends on this to function correctly, I'd consider that to be the problem.Teal
@Teal It depends on it not having the bug mentioned in the FAQ item. localhost and 127.0.0.1 should indeed be statically mapped to each other, and nothing else, and the problem arises when they aren't.Bezoar
This answer should be accepted. Actually, its not misconfiguration. Instead, some linux distirbution (mine is Ubuntu Server 18.04) will assign 127.0.1.1 as your hostname address in /etc/hosts.Azotic
@Azotic And actually that is a misconfiguration, as I described. The fact that Linux does it for you doesn't make it any less a misconfiguration.Bezoar
R
2

I just ran into the same issue. I'm doing something very similar to what you are doing. What I noticed was that the first time I ran the client program, and it failed ( by design of the firewall test ) - that it failed with an error message showing the actual ip address of the host that I originally specified ( the 192.168.x.x address ), but all subsequent failures show that it is failing to make a connection to 127.0.0.1. Currently I'm suspecting some kind of caching on the client - has the JVM marked that ip address as never accessible again and it's refusing to ever try to connect to it again?

UPDATE: In my case, the JVM on the RMI Server side was not able to properly set the java.rmi.server.hostname property at JVM startup. This property was being left as null. When clients connect to a specific RMI Registry and ask for a stub to a particular named object, they receive a stub containing the ip address of the remote machine where the actual object can be found. The RMI server copies the contents of the java.rmi.server.hostname property into the stubs it returns to clients, so if the java.rmi.server.hostname property is "" and it copies that to each stub it creates, each stub contains a reference to remote server with an IP address of "". By default the client jvm reacts to this by attempting to connect to the server object on the localhost, 127.0.0.1. To work around the problem, try this line of code before exporting any remote objects on the server side:

System.setProperty( "java.rmi.server.hostname", "192.168.RMIServer.IP" ) ;

This property will be automatically copied to all remote stubs exported on that server, and clients who receive that stub should then be able to reach the remote server ( assuming any firewalls are configured correctly ).

Ridenhour answered 10/5, 2014 at 17:22 Comment(3)
The property doesn't have to be set, and if it isn't set, RMI gets the hostname via the InetAddress class as explained in my answer. It does not create a reference with "" and the JVM does not 'react to this' in the manner described, because it never happens.Bezoar
Forgive me, I misstated that fact - if the JVM is unable to determine the ip address of the host using methods of the InetAddress class, the java.rmi.server.hostname property is never created at all rather than being created as "". However, I'm still curious - In cases like this, does the server create the stub with no reference to the ip address or hostname of the RMI server, or does the stub get created and automatically populated with 'localhost' or 127.0.0.1 as the location of the remote rmi server?Ridenhour
The stub always has a hostname or IP address of some kind. It looks first at java.rmi.server.hostname, then at whatever InetAddress yields. If it yields 127.0.0.1 that can be because of the misconfiguration described in my answer. It isn't provided by Java.Bezoar

© 2022 - 2024 — McMap. All rights reserved.