JDK-8159410 : InetAddress.isReachable returns true for non existing IP addresses
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 8u91,9
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2016-06-13
  • Updated: 2017-11-29
  • Resolved: 2016-09-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u102Fixed 9 b138Fixed
Description
FULL PRODUCT VERSION :
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) Client VM (build 25.91-b14, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
Microsoft Windows [Version 10.0.10586]

A DESCRIPTION OF THE PROBLEM :
InetAddress.isReachable reports some non existing IP addresses as reachable. Java releases 1.8.0_73 and earlier do not exhibit this problem which had been reported in JDK-8157403, but was closed prematurely.

REGRESSION.  Last worked in version 8u73

ADDITIONAL REGRESSION INFORMATION: 
java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) Client VM (build 25.73-b02, mixed mode)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached program with Java of versions 1.8.0_73 and 1.8.0_91 and enter a random IP address in the IP Address text field followed by an Enter key or a click on the Ping button. The result is shown in the text area.

Examples of the IP addresses:
10.11.1.2
173.168.2.1


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Both versions of Java should show those IP addresses as "NOT an active host".
ACTUAL -
Java version 1.8.0_73 shows those IP addresses as NOT active and 1.8.0_91 as active.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.io.IOException;
import java.net.InetAddress;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class TestPing extends JFrame {
    public TestPing() {
        setTitle(getClass().getSimpleName() + " " + System.getProperty("java.version"));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        JTextArea textArea = new JTextArea();
        textArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setPreferredSize(new Dimension(400, 300));
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        JPanel panel = new JPanel();
        getContentPane().add(panel, BorderLayout.NORTH);

        JLabel lblIpAddress = new JLabel("IP Address");
        panel.add(lblIpAddress);

        JTextField textField = new JTextField();
        panel.add(textField);
        textField.setColumns(11);

        JButton button = new JButton("Ping");
        panel.add(button);
        button.addActionListener((e) -> {
            try {
                Cursor tfCursor = textField.getCursor();
                textField.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                InetAddress address = InetAddress.getByName(textField.getText());
                boolean reachable = address.isReachable(5000);
                textArea.append(address + " machine is " + (reachable ? "" : "NOT ") + "an active host\n");
                textField.setCursor(tfCursor);
                setCursor(Cursor.getDefaultCursor());
            }
            catch (IOException ex) {
                textArea.append("Error: " + ex.getMessage() + "\n");
            }
        });

        textField.addActionListener((e) -> {
            button.doClick();
        });
    }

    public static void main(String[] args) {
        TestPing test = new TestPing();
        test.pack();
        test.setLocationRelativeTo(null);
        test.setVisible(true);
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Using Java of version 1.8.0_73.


Comments
Right now the fix uses a whitelist of expected error codes. Upon receiving an error code not in this list isReachable() will throw an exception. It may be the case that we are missing error codes that we should not thrown exceptions for. If this approach turns out to be too troublesome it may be worth scrapping the exception completely and simply return false instead.
23-09-2016