Keywords: Java RMI | Connection Exception | Hostname Configuration | Remote Method Invocation | Network Programming
Abstract: This article provides an in-depth exploration of the common java.rmi.ConnectException: Connection refused to host error in Java RMI. Through analysis of error stack traces and root causes, it详细 explains the connection failure issue caused by RMI servers using loopback addresses. The article focuses on the solution of properly configuring server hostnames by setting the java.rmi.server.hostname system property, offering complete code examples and configuration guidance to help developers thoroughly resolve connection issues in RMI remote invocations.
Problem Phenomenon and Error Analysis
In Java RMI (Remote Method Invocation) application development, developers frequently encounter the java.rmi.ConnectException: Connection refused to host: 127.0.1.1 exception. This exception indicates that the client's connection attempt to the server was refused, with the root cause being an underlying java.net.ConnectException. From the error stack trace, it's evident that the issue occurs during TCP connection establishment, specifically in the sun.rmi.transport.tcp.TCPEndpoint.newSocket method.
Root Cause Analysis
According to item A.1 in the Oracle official RMI FAQ, the core issue lies in the RMI server binding remote objects using loopback addresses (such as 127.0.0.1 or 127.0.1.1) instead of network addresses accessible by other devices. When remote clients attempt to invoke server methods, the RMI stub contains this loopback address, causing clients to try connecting to the local loopback interface rather than the actual server IP address.
This situation typically occurs in the following scenarios:
- The server does not explicitly set the
java.rmi.server.hostnamesystem property - The operating system's hostname configuration points to a loopback address
- Improper configuration of the /etc/hosts file
Solution Implementation
The most effective solution is to set the java.rmi.server.hostname system property when starting the server. This property specifies the network address through which the RMI server provides services externally, ensuring remote clients can correctly connect to the server.
Here is a specific implementation code example:
// Set hostname property before binding remote objects
System.setProperty("java.rmi.server.hostname", "192.168.1.100");
// Create RMI registry
Registry registry = LocateRegistry.createRegistry(1099);
// Create remote object instance
RemoteServiceImpl remoteService = new RemoteServiceImpl();
// Bind remote object to registry
registry.rebind("RemoteService", remoteService);
System.out.println("RMI server started, listening address: " + System.getProperty("java.rmi.server.hostname"));
Configuration Details and Best Practices
When setting the java.rmi.server.hostname property, pay attention to the following key points:
Property Setting Timing: This property must be set before creating the RMI registry and binding remote objects. If set after object binding, the RMI stub will still contain incorrect address information.
Address Selection Principle: Use the server's actual IP address in the target network, ensuring all clients can access the server through this address. For multi-NIC environments, select the correct network interface address.
Alternative Configuration Methods: Besides setting in code, it can also be configured through JVM startup parameters:
java -Djava.rmi.server.hostname=192.168.1.100 -jar your-server.jar
System-Level Configuration Adjustments
For persistent solutions, consider operating system-level configuration adjustments:
Hosts File Configuration: Check and correct the /etc/hosts file (Linux/Unix systems) or %SystemRoot%\system32\drivers\etc\hosts file (Windows systems), ensuring hostnames correctly map to the server's network IP address rather than loopback addresses.
Network Interface Binding: In some cases, it may be necessary to explicitly specify the network interface to which the RMI server binds, avoiding the default loopback interface.
Verification and Testing
After implementing the solution, comprehensive connection testing is required:
First, verify on the server side that the RMI registry started correctly and check the address information of bound remote objects. Then perform connection tests from remote clients to ensure successful remote method invocation.
Use the following code snippet for basic connection testing:
try {
Registry registry = LocateRegistry.getRegistry("192.168.1.100", 1099);
RemoteService service = (RemoteService) registry.lookup("RemoteService");
String result = service.executeMethod("test");
System.out.println("Remote invocation successful: " + result);
} catch (Exception e) {
System.err.println("Connection test failed: " + e.getMessage());
}
Conclusion
The root cause of the java.rmi.ConnectException: Connection refused to host: 127.0.1.1 error is the RMI server using loopback addresses inaccessible from external networks. By correctly setting the java.rmi.server.hostname system property, you can ensure RMI stubs contain the correct network address, thereby resolving remote connection issues. This method is simple and effective, serving as the standard solution for handling such RMI connection problems.