Index: /trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 12216)
+++ /trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 12217)
@@ -84,6 +84,10 @@
         String runtimeVersion = System.getProperty("java.runtime.version");
         text.append(Version.getInstance().getReleaseAttributes())
-            .append("\nIdentification: ").append(Version.getInstance().getAgentString())
-            .append("\nMemory Usage: ")
+            .append("\nIdentification: ").append(Version.getInstance().getAgentString());
+        String buildNumber = Main.platform.getOSBuildNumber();
+        if (!buildNumber.isEmpty()) {
+            text.append("\nOS Build number: ").append(buildNumber);
+        }
+        text.append("\nMemory Usage: ")
             .append(Runtime.getRuntime().totalMemory()/1024/1024)
             .append(" MB / ")
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHook.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHook.java	(revision 12216)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHook.java	(revision 12217)
@@ -3,6 +3,9 @@
 
 import java.awt.GraphicsEnvironment;
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -140,4 +143,13 @@
 
     /**
+     * Returns OS build number.
+     * @return OS build number.
+     * @since 12217
+     */
+    default String getOSBuildNumber() {
+        return "";
+    }
+
+    /**
      * Setup system keystore to add JOSM HTTPS certificate (for remote control).
      * @param entryAlias The entry alias to use
@@ -172,4 +184,18 @@
 
     /**
+     * Executes a native command and returns the first line of standard output.
+     * @param command array containing the command to call and its arguments.
+     * @return first stripped line of standard output
+     * @throws IOException if an I/O error occurs
+     * @since 12217
+     */
+    default String exec(String... command) throws IOException {
+        Process p = Runtime.getRuntime().exec(command);
+        try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
+            return Utils.strip(input.readLine());
+        }
+    }
+
+    /**
      * Returns the platform-dependent default cache directory.
      * @return the platform-dependent default cache directory
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java	(revision 12216)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java	(revision 12217)
@@ -32,4 +32,6 @@
 
     private static final PlatformHookOsx ivhandler = new PlatformHookOsx();
+
+    private String oSBuildNumber;
 
     @Override
@@ -386,4 +388,27 @@
     }
 
+    private String buildOSBuildNumber() {
+        StringBuilder sb = new StringBuilder();
+        try {
+            sb.append(exec("sw_vers", "-productName"))
+              .append(' ')
+              .append(exec("sw_vers", "-productVersion"))
+              .append(" (")
+              .append(exec("sw_vers", "-buildVersion"))
+              .append(')');
+        } catch (IOException e) {
+            Main.error(e);
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String getOSBuildNumber() {
+        if (oSBuildNumber == null) {
+            oSBuildNumber = buildOSBuildNumber();
+        }
+        return oSBuildNumber;
+    }
+
     @Override
     public File getDefaultCacheDirectory() {
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java	(revision 12216)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java	(revision 12217)
@@ -10,5 +10,4 @@
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -207,15 +206,12 @@
                 // Try lsb_release (only available on LSB-compliant Linux systems,
                 // see https://www.linuxbase.org/lsb-cert/productdir.php?by_prod )
-                Process p = Runtime.getRuntime().exec("lsb_release -ds");
-                try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
-                    String line = Utils.strip(input.readLine());
-                    if (line != null && !line.isEmpty()) {
-                        line = line.replaceAll("\"+", "");
-                        line = line.replaceAll("NAME=", ""); // strange code for some Gentoo's
-                        if (line.startsWith("Linux ")) // e.g. Linux Mint
-                            return line;
-                        else if (!line.isEmpty())
-                            return "Linux " + line;
-                    }
+                String line = exec("lsb_release -ds");
+                if (line != null && !line.isEmpty()) {
+                    line = line.replaceAll("\"+", "");
+                    line = line.replaceAll("NAME=", ""); // strange code for some Gentoo's
+                    if (line.startsWith("Linux ")) // e.g. Linux Mint
+                        return line;
+                    else if (!line.isEmpty())
+                        return "Linux " + line;
                 }
             } catch (IOException e) {
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 12216)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 12217)
@@ -27,4 +27,5 @@
 import static java.awt.event.KeyEvent.VK_Z;
 import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.WinRegistry.HKEY_LOCAL_MACHINE;
 
 import java.awt.GraphicsEnvironment;
@@ -36,4 +37,5 @@
 import java.io.OutputStreamWriter;
 import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.DirectoryStream;
@@ -64,7 +66,9 @@
 
 import javax.swing.JOptionPane;
+import javax.swing.UIManager;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.gui.preferences.display.LafPreference;
 import org.openstreetmap.josm.io.CertificateAmendment.CertAmend;
 
@@ -150,7 +154,30 @@
     private static final String WINDOWS_ROOT = "Windows-ROOT";
 
+    private static final String CURRENT_VERSION = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
+
+    private String oSBuildNumber;
+
     @Override
     public void afterPrefStartupHook() {
         extendFontconfig("fontconfig.properties.src");
+        // Workaround for JDK-8180379: crash on Windows 10 1703 with Windows L&F and java < 8u152 / 9+171
+        // To remove during Java 9 migration
+        if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows 10") &&
+                getDefaultStyle().equals(LafPreference.LAF.get())) {
+            try {
+                final int currentBuild = Integer.parseInt(getCurrentBuild());
+                final int javaVersion = Utils.getJavaVersion();
+                final int javaUpdate = Utils.getJavaUpdate();
+                final int javaBuild = Utils.getJavaBuild();
+                // See https://technet.microsoft.com/en-us/windows/release-info.aspx
+                if (currentBuild >= 15_063 && ((javaVersion == 8 && javaUpdate < 152)
+                        || (javaVersion == 9 && javaUpdate == 0 && javaBuild < 171))) {
+                    // Workaround from https://bugs.openjdk.java.net/browse/JDK-8179014
+                    UIManager.put("FileChooser.useSystemExtensionHiding", false);
+                }
+            } catch (NumberFormatException | ReflectiveOperationException e) {
+                Main.error(e);
+            }
+        }
     }
 
@@ -250,4 +277,36 @@
     }
 
+    private static String getProductName() throws IllegalAccessException, InvocationTargetException {
+        return WinRegistry.readString(HKEY_LOCAL_MACHINE, CURRENT_VERSION, "ProductName");
+    }
+
+    private static String getReleaseId() throws IllegalAccessException, InvocationTargetException {
+        return WinRegistry.readString(HKEY_LOCAL_MACHINE, CURRENT_VERSION, "ReleaseId");
+    }
+
+    private static String getCurrentBuild() throws IllegalAccessException, InvocationTargetException {
+        return WinRegistry.readString(HKEY_LOCAL_MACHINE, CURRENT_VERSION, "CurrentBuild");
+    }
+
+    private static String buildOSBuildNumber() {
+        StringBuilder sb = new StringBuilder();
+        try {
+            sb.append(getProductName()).append(' ')
+              .append(getReleaseId()).append(" (")
+              .append(getCurrentBuild()).append(')');
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            Main.error(e);
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String getOSBuildNumber() {
+        if (oSBuildNumber == null) {
+            oSBuildNumber = buildOSBuildNumber();
+        }
+        return oSBuildNumber;
+    }
+
     /**
      * Loads Windows-ROOT keystore.
Index: /trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 12216)
+++ /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 12217)
@@ -1607,3 +1607,42 @@
                 dotPos > -1 ? dotPos : dashPos > -1 ? dashPos : 1));
     }
+
+    /**
+     * Returns the Java update as an int value.
+     * @return the Java update as an int value (121, 131, etc.)
+     * @since 12217
+     */
+    public static int getJavaUpdate() {
+        String version = System.getProperty("java.version");
+        if (version.startsWith("1.")) {
+            version = version.substring(2);
+        }
+        // Allow these formats:
+        // 1.8.0_72-ea
+        // 9-ea
+        // 9
+        // 9.0.1
+        int undePos = version.indexOf('_');
+        int dashPos = version.indexOf('-');
+        if (undePos > -1) {
+            return Integer.parseInt(version.substring(undePos + 1,
+                    dashPos > -1 ? dashPos : version.length()));
+        }
+        int firstDotPos = version.indexOf('.');
+        int lastDotPos = version.lastIndexOf('.');
+        return firstDotPos > - 1 ? Integer.parseInt(version.substring(firstDotPos + 1,
+                lastDotPos > -1 ? lastDotPos : version.length())) : 0;
+    }
+
+    /**
+     * Returns the Java build number as an int value.
+     * @return the Java build number as an int value (0, 1, etc.)
+     * @since 12217
+     */
+    public static int getJavaBuild() {
+        String version = System.getProperty("java.runtime.version");
+        int bPos = version.indexOf('b');
+        int pPos = version.indexOf('+');
+        return Integer.parseInt(version.substring(bPos > -1 ? bPos + 1 : pPos + 1, version.length()));
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/tools/WinRegistry.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/WinRegistry.java	(revision 12217)
+++ /trunk/src/org/openstreetmap/josm/tools/WinRegistry.java	(revision 12217)
@@ -0,0 +1,210 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.tools;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.prefs.Preferences;
+
+/**
+ * Utility class to access Window registry (read access only).
+ * As the implementation relies on internal JDK class {@code java.util.prefs.WindowsPreferences} and its native JNI
+ * method {@code Java_java_util_prefs_WindowsPreferences_WindowsRegQueryValueEx}, only String values (REG_SZ)
+ * are supported.
+ * Adapted from <a href="http://stackoverflow.com/a/6163701/2257172">StackOverflow</a>.
+ * @since 12217
+ */
+public final class WinRegistry {
+
+    /**
+     * Registry entries subordinate to this key define the preferences of the current user.
+     * These preferences include the settings of environment variables, data about program groups,
+     * colors, printers, network connections, and application preferences.
+     * See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
+     */
+    public static final int HKEY_CURRENT_USER = 0x80000001;
+
+    /**
+     * Registry entries subordinate to this key define the physical state of the computer, including data about the bus type,
+     * system memory, and installed hardware and software. It contains subkeys that hold current configuration data,
+     * including Plug and Play information (the Enum branch, which includes a complete list of all hardware that has ever been
+     * on the system), network logon preferences, network security information, software-related information (such as server
+     * names and the location of the server), and other system information.
+     * See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
+     */
+    public static final int HKEY_LOCAL_MACHINE = 0x80000002;
+
+    private static final int REG_SUCCESS = 0;
+
+    private static final int KEY_READ = 0x20019;
+    private static final Preferences userRoot = Preferences.userRoot();
+    private static final Preferences systemRoot = Preferences.systemRoot();
+    private static final Class<? extends Preferences> userClass = userRoot.getClass();
+    private static final Method regOpenKey;
+    private static final Method regCloseKey;
+    private static final Method regQueryValueEx;
+    private static final Method regEnumValue;
+    private static final Method regQueryInfoKey;
+    private static final Method regEnumKeyEx;
+
+    static {
+        try {
+            regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey",
+                    new Class[] { int.class, byte[].class, int.class });
+            regOpenKey.setAccessible(true);
+            regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey",
+                    new Class[] { int.class });
+            regCloseKey.setAccessible(true);
+            regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx",
+                    new Class[] { int.class, byte[].class });
+            regQueryValueEx.setAccessible(true);
+            regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue",
+                    new Class[] { int.class, int.class, int.class });
+            regEnumValue.setAccessible(true);
+            regQueryInfoKey = userClass.getDeclaredMethod("WindowsRegQueryInfoKey1",
+                    new Class[] { int.class });
+            regQueryInfoKey.setAccessible(true);
+            regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx",
+                    new Class[] { int.class, int.class, int.class });
+            regEnumKeyEx.setAccessible(true);
+        } catch (SecurityException | ReflectiveOperationException e) {
+            throw new JosmRuntimeException(e);
+        }
+    }
+
+    private WinRegistry() {
+        // Hide default constructor for utilities classes
+    }
+
+    /**
+     * Read a value from key and value name
+     * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+     * @param key  key name
+     * @param valueName  value name
+     * @return the value
+     * @throws IllegalArgumentException if hkey not HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+     * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
+     * @throws InvocationTargetException if the underlying method throws an exception
+     */
+    public static String readString(int hkey, String key, String valueName)
+            throws IllegalAccessException, InvocationTargetException {
+        if (hkey == HKEY_LOCAL_MACHINE) {
+            return readString(systemRoot, hkey, key, valueName);
+        } else if (hkey == HKEY_CURRENT_USER) {
+            return readString(userRoot, hkey, key, valueName);
+        } else {
+            throw new IllegalArgumentException("hkey=" + hkey);
+        }
+    }
+
+    /**
+     * Read value(s) and value name(s) form given key
+     * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+     * @param key  key name
+     * @return the value name(s) plus the value(s)
+     * @throws IllegalArgumentException if hkey not HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+     * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
+     * @throws InvocationTargetException if the underlying method throws an exception
+     */
+    public static Map<String, String> readStringValues(int hkey, String key)
+            throws IllegalAccessException, InvocationTargetException {
+        if (hkey == HKEY_LOCAL_MACHINE) {
+            return readStringValues(systemRoot, hkey, key);
+        } else if (hkey == HKEY_CURRENT_USER) {
+            return readStringValues(userRoot, hkey, key);
+        } else {
+            throw new IllegalArgumentException("hkey=" + hkey);
+        }
+    }
+
+    /**
+     * Read the value name(s) from a given key
+     * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+     * @param key  key name
+     * @return the value name(s)
+     * @throws IllegalArgumentException if hkey not HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+     * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
+     * @throws InvocationTargetException if the underlying method throws an exception
+     */
+    public static List<String> readStringSubKeys(int hkey, String key)
+            throws IllegalAccessException, InvocationTargetException {
+        if (hkey == HKEY_LOCAL_MACHINE) {
+            return readStringSubKeys(systemRoot, hkey, key);
+        } else if (hkey == HKEY_CURRENT_USER) {
+            return readStringSubKeys(userRoot, hkey, key);
+        } else {
+            throw new IllegalArgumentException("hkey=" + hkey);
+        }
+    }
+
+    // =====================
+
+    private static String readString(Preferences root, int hkey, String key, String value)
+            throws IllegalAccessException, InvocationTargetException {
+        int[] handles = (int[]) regOpenKey.invoke(root,
+                new Object[] { Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ) });
+        if (handles[1] != REG_SUCCESS) {
+            return null;
+        }
+        byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] { Integer.valueOf(handles[0]), toCstr(value) });
+        regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) });
+        return (valb != null ? new String(valb, StandardCharsets.UTF_8).trim() : null);
+    }
+
+    private static Map<String, String> readStringValues(Preferences root, int hkey, String key)
+            throws IllegalAccessException, InvocationTargetException {
+        HashMap<String, String> results = new HashMap<>();
+        int[] handles = (int[]) regOpenKey.invoke(root,
+                new Object[] { Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ) });
+        if (handles[1] != REG_SUCCESS) {
+            return null;
+        }
+        int[] info = (int[]) regQueryInfoKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) });
+
+        int count = info[0]; // count
+        int maxlen = info[3]; // value length max
+        for (int index = 0; index < count; index++) {
+            byte[] name = (byte[]) regEnumValue.invoke(root,
+                    new Object[] { Integer.valueOf(handles[0]), Integer.valueOf(index), Integer.valueOf(maxlen + 1) });
+            String value = readString(hkey, key, new String(name, StandardCharsets.UTF_8));
+            results.put(new String(name, StandardCharsets.UTF_8).trim(), value);
+        }
+        regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) });
+        return results;
+    }
+
+    private static List<String> readStringSubKeys(Preferences root, int hkey, String key)
+            throws IllegalAccessException, InvocationTargetException {
+        List<String> results = new ArrayList<>();
+        int[] handles = (int[]) regOpenKey.invoke(root,
+                new Object[] { Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ) });
+        if (handles[1] != REG_SUCCESS) {
+            return Collections.emptyList();
+        }
+        int[] info = (int[]) regQueryInfoKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) });
+
+        int count = info[0]; // Fix: info[2] was being used here with wrong results. Suggested by davenpcj, confirmed by Petrucio
+        int maxlen = info[3]; // value length max
+        for (int index = 0; index < count; index++) {
+            byte[] name = (byte[]) regEnumKeyEx.invoke(root,
+                    new Object[] { Integer.valueOf(handles[0]), Integer.valueOf(index), Integer.valueOf(maxlen + 1) });
+            results.add(new String(name, StandardCharsets.UTF_8).trim());
+        }
+        regCloseKey.invoke(root, new Object[] { Integer.valueOf(handles[0]) });
+        return results;
+    }
+
+    // utility
+    private static byte[] toCstr(String str) {
+        byte[] array = str.getBytes(StandardCharsets.UTF_8);
+        byte[] biggerCopy = Arrays.copyOf(array, array.length + 1);
+        biggerCopy[array.length] = 0;
+        return biggerCopy;
+    }
+}
Index: /trunk/test/unit/org/openstreetmap/josm/tools/UtilsTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/tools/UtilsTest.java	(revision 12216)
+++ /trunk/test/unit/org/openstreetmap/josm/tools/UtilsTest.java	(revision 12217)
@@ -219,4 +219,56 @@
 
     /**
+     * Test {@link Utils#getJavaUpdate}
+     */
+    @Test
+    public void testGetJavaUpdate() {
+        String javaVersion = System.getProperty("java.version");
+        try {
+            System.setProperty("java.version", "1.8.0_131");
+            assertEquals(131, Utils.getJavaUpdate());
+
+            System.setProperty("java.version", "1.8.0_152-ea");
+            assertEquals(152, Utils.getJavaUpdate());
+
+            System.setProperty("java.version", "9-ea");
+            assertEquals(0, Utils.getJavaUpdate());
+
+            System.setProperty("java.version", "9");
+            assertEquals(0, Utils.getJavaUpdate());
+
+            System.setProperty("java.version", "9.1.2");
+            assertEquals(1, Utils.getJavaUpdate());
+        } finally {
+            System.setProperty("java.version", javaVersion);
+        }
+    }
+
+    /**
+     * Test {@link Utils#getJavaBuild}
+     */
+    @Test
+    public void testGetJavaBuild() {
+        String javaVersion = System.getProperty("java.runtime.version");
+        try {
+            System.setProperty("java.runtime.version", "1.8.0_131-b11");
+            assertEquals(11, Utils.getJavaBuild());
+
+            System.setProperty("java.runtime.version", "1.8.0_152-ea-b04");
+            assertEquals(4, Utils.getJavaBuild());
+
+            System.setProperty("java.runtime.version", "9-ea+170");
+            assertEquals(170, Utils.getJavaBuild());
+
+            System.setProperty("java.runtime.version", "9+200");
+            assertEquals(200, Utils.getJavaBuild());
+
+            System.setProperty("java.runtime.version", "9.1.2+62");
+            assertEquals(62, Utils.getJavaBuild());
+        } finally {
+            System.setProperty("java.runtime.version", javaVersion);
+        }
+    }
+
+    /**
      * Tests if readBytesFromStream handles null streams (might happen when there is no data on error stream)
      * @throws IOException in case of I/O error
