Bug 239890

Summary: java/openjdk11: openjdk 11.0.4+11.2 JDBC connections fail with IPv6 addresses
Product: Ports & Packages Reporter: Jonathan Chen <jonc>
Component: Individual Port(s)Assignee: freebsd-java mailing list <java>
Status: New ---    
Severity: Affects Only Me CC: glewis
Priority: --- Flags: bugzilla: maintainer-feedback? (java)
Version: Latest   
Hardware: Any   
OS: Any   

Description Jonathan Chen 2019-08-15 21:27:19 UTC
1.stormblade:jdbc-test,9:19am> cat J.java 
import java.sql.*;

public class J
{
        public static void
        main (
                String args[])
                throws Exception
        {
                String url = "jdbc:postgresql://[::1]/postgres?user=postgres";
                Connection conn = DriverManager.getConnection(url);
        }
}
1.stormblade:jdbc-test,9:20am> fetch https://jdbc.postgresql.org/download/postgresql-42.2.6.jar
postgresql-42.2.6.jar                                  823 kB  337 kBps    03s
1.stormblade:jdbc-test,9:20am> setenv JAVA_HOME /usr/local/openjdk8
1.stormblade:jdbc-test,9:20am> javac J.java 
1.stormblade:jdbc-test,9:21am> java -cp .:postgresql-42.2.6.jar J
1.stormblade:jdbc-test,9:21am> setenv JAVA_HOME /usr/local/openjdk11
1.stormblade:jdbc-test,9:21am> java -cp .:postgresql-42.2.6.jar J
Exception in thread "main" org.postgresql.util.PSQLException: The connection attempt failed.
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:292)
        at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
        at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
        at org.postgresql.Driver.makeConnection(Driver.java:458)
        at org.postgresql.Driver.connect(Driver.java:260)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
        at J.main(J.java:11)
Caused by: java.net.SocketException: Protocol family unavailable
        at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
        at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
        at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)
        at java.base/java.net.Socket.connect(Socket.java:591)
        at org.postgresql.core.PGStream.<init>(PGStream.java:75)
        at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:91)
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:192)
        ... 7 more
1.stormblade:jdbc-test,9:24am> java -version
openjdk version "11.0.4" 2019-07-16
OpenJDK Runtime Environment (build 11.0.4+11-2)
OpenJDK 64-Bit Server VM (build 11.0.4+11-2, mixed mode)
Comment 1 Greg Lewis freebsd_committer 2019-08-20 08:59:09 UTC
openjdk11 now prefers IPv4 addresses by default, i.e. the java.net.preferIPv4Stack property is now set to true by default.  Try setting it to false.

Without this a number of the internal jdk tests fail.
Comment 2 Jonathan Chen 2019-08-20 19:15:33 UTC
This appears to have worked:

7:08am> java -cp .:postgresql-42.2.6.jar -Djava.net.preferIPv4Stack=false J
7:08am> 

However, this small code snippet worked with the version before this, 11.0.4+11.1_2. Did the the preferIPv4Stack change with the latest version?

As this is a "preference", shouldn't the explicit use of an IPv6 address, ie [::1], indicate that the "preference" be ignored? Or did I misunderstand the semantics of java.net.preferIPv4Stack?
Comment 3 Greg Lewis freebsd_committer 2019-08-20 20:01:13 UTC
Yes, this was a change in the latest version.  Without it, tests which set socket options, for example, would consistently fail due to how the JVM assumes the OS handles dual mode sockets.  There is a better fix than this, but it requires substantial work.

I believe that based on how the socket code works at the moment, the handling on BSD means that "prefer" is a bit of a misnomer.  I can add a caveat to pkg-message regarding this since that might be helpful.
Comment 4 Jonathan Chen 2019-08-20 20:05:06 UTC
Note that according to:

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/doc-files/net-properties.html

java.net.preferIPv4Stack defaults to "false", so our pkg-message should state this is a BSD-ism.
Comment 5 Jonathan Chen 2019-08-20 20:34:15 UTC
Actually, it looks like the use of java.net.preferIPv4Stack=true is actually hiding a problem with OpenJDK11's IP address handling:

1.stormblade:jdbc-test,8:31am> ls    
J.java                 postgresql-42.2.6.jar    
1.stormblade:jdbc-test,8:31am> cat J.java     
import java.sql.*;  
  
public class J  
{  
        public static void  
        main (  
                String args[])  
                throws Exception  
        {  
                String url = "jdbc:postgresql://127.0.0.1/postgres?user=postgres";  
                Connection conn = DriverManager.getConnection(url);  
        }  
}  
1.stormblade:jdbc-test,8:31am> setenv JAVA_HOME /usr/local/openjdk8
1.stormblade:jdbc-test,8:31am> javac J.java    
1.stormblade:jdbc-test,8:31am> java -cp .:postgresql-42.2.6.jar -Djava.net.preferIPv4Stack=false J   
1.stormblade:jdbc-test,8:32am> setenv JAVA_HOME /usr/local/openjdk11    
1.stormblade:jdbc-test,8:32am> java -cp .:postgresql-42.2.6.jar -Djava.net.preferIPv4Stack=false J    
Exception in thread "main" org.postgresql.util.PSQLException: Connection to 127.0.0.1:5432 refused. Check that the hostname and port are correct and that the
 postmaster is accepting TCP/IP connections.  
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:280)  
        at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)  
        at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)  
        at org.postgresql.Driver.makeConnection(Driver.java:458)  
        at org.postgresql.Driver.connect(Driver.java:260)  
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)  
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)  
        at J.main(J.java:11)  
Caused by: java.net.ConnectException: Invalid argument (connect failed)  
        at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)  
        at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)  
        at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)  
        at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)  
        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)  
        at java.base/java.net.Socket.connect(Socket.java:591)  
        at org.postgresql.core.PGStream.<init>(PGStream.java:75)  
        at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:91)  
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:192)  
        ... 7 more  
1.stormblade:jdbc-test,8:32am>
Comment 6 Greg Lewis freebsd_committer 2019-08-21 16:42:26 UTC
That's what I expect at the moment.  We'll either handle IPv4 addresses correctly (with the defaults) or we'll handle IPv6 addresses correctly (if you set java.net.preferIPv4Stack to false).  At the moment you can't do both.  Previously it did both brokenly.  I don't think there is an easy way to have both work correctly on BSD.

I can look into this code more deeply, but it'll probably take a while since I think there are some things that are higher priority right now.