问题
We just upgraded to Java 8 on Amazon Linux. We are using Spring 4.3.8.RELEASE. It used to be that we could get our machine hostname by setting up beans in our application context file like so ...
<bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="hostname" factory-bean="localhostInetAddress" factory-method="getHostName" />
But with Java 8, the bean "hostname" now contains the string
localhost
Before Java 8, it used to contain the "hostname" value as run on the command line, which is
[myuser@machine1 ~]$ hostname
machine1.mydomain.org
How can I reconfigure our bean so that it gets the hostname that the command line lists out? I don't want to hard-code anything anywhere.
回答1:
There are a similar question in the OpenJDK bugs
The newer calls respect the localhosts /etc/nsswitch.conf configuration files. In the case of this machine that file tells these calls to look in files before referencing other naming services.
Since the /etc/hosts file contains an explicit mapping for this hostname / IP combination, that is what is returned.
In the older JDK's the gethostbyname actually ignored the local machines settings and immediately delegated to the naming service.
You can always use the Runtime class for that :
Process hostname = Runtime.getRuntime().exec("hostname");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(hostname.getInputStream()));
String s;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
But it's not so recommended as you can see
回答2:
From InetAddress java 8 is not getting the hostname :
There was similar bug fired in JDK.
What I understand is that they changed default resolution process.
They honor configuration in /etc/nsswitch.conf where hosts are configured for /etc/hosts that gives it main priority for name resolution.
Usually /etc/hosts has record for 127.0.0.1 localhost that provide name for host localhost
回答3:
You could try InetAddress.getCanonicalHostName()
The JavaDocs for getCanonicalHostName() says
Gets the fully qualified domain name for this IP address. Best effort method, meaning we may not be able to return the FQDN depending on the underlying system configuration.
回答4:
You really have three options of differing complexity and information value:
- Actually run the hostname command using Runtime. It's fairly portable and should work pretty much everywhere. (Maybe not on IBM's Mainframes)
- Grab all available network interfaces and get their hostnames. https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
- Set an environment or system property as the value of hostname.
Like java -Dmy.hostname=hostname
...
Sad part is that it's not that straightforward in Spring XML.
All other options are known to give varying degrees of accuracy. Like 127.0.0.1 will likely resolve to localhost or localhost.localdomain.
回答5:
Alternatively, you can run the hostname linux command using Java Runtime, code should be something like below:
String cmdResult="";
Runtime r = Runtime.getRuntime();
Process p = r.exec("hostname");
BufferedReader in = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
cmdResult += inputLine;
}
in.close();
回答6:
Since my comment got lost in the stream, please try
<bean id="hostname" class="com.amazonaws.util.EC2MetadataUtils" factory-method="getLocalHostName()">
Have a look at Amazon's documemtation if the result does not suits your needs.
回答7:
I can be better to define a property in your .properties file for hostname like.
hostname=myserver.mydomain.com
And use it in your application. This way is not harcoded. It also avoid dependency to operating system config which can be changed without attention.
回答8:
InetAddress in Java 8 had a bug regarding the resolution of hostname. The bug was reported in version 8u20 and has been fixed since then. Please check that you are not on this version. If not, then using InetAddress.getLocalHost().getHostName()
will give you the hostname.
Also I suggest, setting up a static hostname on the AWS instance.
- Update /etc/hosts
- Update /etc/hostname
- Run
hostname
to check the hostname - Reboot and check the persisted hostname
This should allow you to read the hostname from the file if required.
Also, if hostname
command is giving the correct result, then use exec method in Runtime class to execute the command and the read the InputStream to get the response.
PS: You can use InetAddress.getLocalHost().isLoopbackAddress()
to check whether the address is a LoopbackAddress and then use a fallback method.
回答9:
I believe Java still calls the native gethostname()
, but couldn't say why this fails.
For Linux, you could try this alternative:
String hostname = new String(Files.readAllBytes(Paths.get("/proc/sys/kernel/hostname")), StandardCharsets.US_ASCII);
来源:https://stackoverflow.com/questions/48325178/in-java-8-how-do-i-get-my-hostname-without-hard-coding-it-in-my-environment