When using com.sun.net.httpserver.HttpServer
, I observed the following in an application:
- When run not from a jar (e.g. from Eclipse or on command line)
System.setProperty("java.net.preferIPv4Stack", "true")
,HttpServer.getAddress()
returns an IPv4 address as expected. - When run from an executable jar generated by hand (i.e.
jar cvfe ...
rather than Eclipse export), it also returns an IPv4 address as expected. - When run from an Eclipse-generated runnable jar (either from command line or the shell), it returns an IPv6 address unless
-Djava.net.preferIPv4Stack=true
is specified on the command line. That is, it honors the command line setting but ignores theSystem.setProperty()
, only when run from a jar exported by Eclipse.
I looked at the source and was able to create a simple test with ServerSocketChannel
:
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.ServerSocketChannel;
public class IP4Test {
public static void main (String[] args) throws Exception {
System.setProperty("java.net.preferIPv4Stack", "true");
InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 80);
ServerSocketChannel schan = ServerSocketChannel.open();
ServerSocket socket = schan.socket();
socket.bind(addr);
System.out.println(socket.getLocalSocketAddress());
}
}
When run from a class file with the property set to "true" in the code, it outputs:
/0.0.0.0:80
When run from a class file with the property set to "false" (or not set) in the code, it outputs:
/0:0:0:0:0:0:0:0:80
This is as expected.
When run from a hand-generated jar (e.g. jar cvfe IP4Test.jar IP4Test IP4Test.class
) it behaves as expected as well.
However, when exported to a runnable jar from Eclipse and run from anywhere (command line or shell), it outputs an IPv6 address regardless of what the property was set to in code -- yet, specifying -Djava.net.preferIPv4Stack=true
on the command line, it outputs an IPv4 address.
That is, it works as expected when run from class files and hand-generated jar files, but from an Eclipse-generated jar it ignores the System.setProperty()
call but still obeys the command line.
Why is System.setProperty("java.net.preferIPv4Stack")
being ignored when the application is exported to a jar from Eclipse, why is it different than the behavior of no / hand-generated jar, and how can I make it work properly?
Edit: After reading prunge's answer I tried a hand-generated JAR (previously I was using Eclipse) and discovered that the behavior was unique to Eclipse-generated JARs, rather than JARs in general. I modified the above question to reflect that. Prunge's theory seems the most likely - whether or not it's PlainSocketImpl or something else indirectly related to one of the org.eclipse classes that Eclipse puts in the JAR, I do not know. Mostly I want to point out that the answer was posted before this most recent edit.
Update: Actually it's not unique to Eclipse. Even with a hand-generated jar that "works", if I, say, override the security manager on the command line, it stops working. This all even more strongly supports prunge's answer. I may never be able to figure out what class does it but the answer is absolutely to specify the property on the command line and not do it in code. At this point, I'm tired of rewriting the above question.