Index: src/org/openstreetmap/josm/Main.java
===================================================================
--- src/org/openstreetmap/josm/Main.java	(revision 12983)
+++ src/org/openstreetmap/josm/Main.java	(working copy)
@@ -48,6 +48,7 @@
 import org.openstreetmap.josm.io.FileWatcher;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.plugins.PluginHandler;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -761,6 +762,7 @@
         } catch (IOException ex) {
             Logging.log(Logging.LEVEL_WARN, tr("Failed to save default preferences."), ex);
         }
+        PluginHandler.shutdown();
         if (!GraphicsEnvironment.isHeadless()) {
             ImageProvider.shutdown(true);
         }
Index: src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- src/org/openstreetmap/josm/data/Preferences.java	(revision 12990)
+++ src/org/openstreetmap/josm/data/Preferences.java	(working copy)
@@ -5,8 +5,6 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Color;
-import java.awt.GraphicsEnvironment;
-import java.awt.Toolkit;
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -14,7 +12,6 @@
 import java.io.StringWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Field;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -27,7 +24,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
-import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.TreeMap;
@@ -45,6 +41,7 @@
 import org.openstreetmap.josm.data.preferences.DoubleProperty;
 import org.openstreetmap.josm.data.preferences.IntegerProperty;
 import org.openstreetmap.josm.data.preferences.ColorInfo;
+import org.openstreetmap.josm.data.preferences.JosmBaseDirectories;
 import org.openstreetmap.josm.data.preferences.LongProperty;
 import org.openstreetmap.josm.data.preferences.NamedColorProperty;
 import org.openstreetmap.josm.data.preferences.PreferencesReader;
@@ -102,24 +99,9 @@
 
     private static final long MAX_AGE_DEFAULT_PREFERENCES = TimeUnit.DAYS.toSeconds(50);
 
-    /**
-     * Internal storage for the preference directory.
-     * Do not access this variable directly!
-     * @see #getPreferencesDirectory()
-     */
-    private File preferencesDir;
+    private final IBaseDirectories dirs;
 
     /**
-     * Internal storage for the cache directory.
-     */
-    private File cacheDir;
-
-    /**
-     * Internal storage for the user data directory.
-     */
-    private File userdataDir;
-
-    /**
      * Determines if preferences file is saved each time a property is changed.
      */
     private boolean saveOnPut = true;
@@ -246,8 +228,13 @@
      */
     public Preferences() {
         // Default constructor
+        this.dirs = new JosmBaseDirectories();
     }
 
+    public Preferences(IBaseDirectories dirs) {
+        this.dirs = dirs;
+    }
+
     /**
      * Constructs a new {@code Preferences} from an existing instance.
      * @param pref existing preferences to copy
@@ -255,6 +242,7 @@
      */
     @SuppressWarnings("deprecation")
     public Preferences(Preferences pref) {
+        this(pref.dirs);
         settingsMap.putAll(pref.settingsMap);
         defaultsMap.putAll(pref.defaultsMap);
         colornames.putAll(pref.colornames);
@@ -431,30 +419,7 @@
 
     @Override
     public File getPreferencesDirectory(boolean createIfMissing) {
-        if (preferencesDir == null) {
-            String path;
-            path = System.getProperty("josm.pref");
-            if (path != null) {
-                preferencesDir = new File(path).getAbsoluteFile();
-            } else {
-                path = System.getProperty("josm.home");
-                if (path != null) {
-                    preferencesDir = new File(path).getAbsoluteFile();
-                } else {
-                    preferencesDir = Main.platform.getDefaultPrefDirectory();
-                }
-            }
-        }
-        if (createIfMissing && !preferencesDir.exists() && !preferencesDir.mkdirs()) {
-            Logging.warn(tr("Failed to create missing preferences directory: {0}", preferencesDir.getAbsoluteFile()));
-            JOptionPane.showMessageDialog(
-                    Main.parent,
-                    tr("<html>Failed to create missing preferences directory: {0}</html>", preferencesDir.getAbsoluteFile()),
-                    tr("Error"),
-                    JOptionPane.ERROR_MESSAGE
-            );
-        }
-        return preferencesDir;
+        return dirs.getPreferencesDirectory(createIfMissing);
     }
 
     /**
@@ -471,30 +436,7 @@
 
     @Override
     public File getUserDataDirectory(boolean createIfMissing) {
-        if (userdataDir == null) {
-            String path;
-            path = System.getProperty("josm.userdata");
-            if (path != null) {
-                userdataDir = new File(path).getAbsoluteFile();
-            } else {
-                path = System.getProperty("josm.home");
-                if (path != null) {
-                    userdataDir = new File(path).getAbsoluteFile();
-                } else {
-                    userdataDir = Main.platform.getDefaultUserDataDirectory();
-                }
-            }
-        }
-        if (createIfMissing && !userdataDir.exists() && !userdataDir.mkdirs()) {
-            Logging.warn(tr("Failed to create missing user data directory: {0}", userdataDir.getAbsoluteFile()));
-            JOptionPane.showMessageDialog(
-                    Main.parent,
-                    tr("<html>Failed to create missing user data directory: {0}</html>", userdataDir.getAbsoluteFile()),
-                    tr("Error"),
-                    JOptionPane.ERROR_MESSAGE
-            );
-        }
-        return userdataDir;
+        return dirs.getUserDataDirectory(createIfMissing);
     }
 
     /**
@@ -536,34 +478,7 @@
 
     @Override
     public File getCacheDirectory(boolean createIfMissing) {
-        if (cacheDir == null) {
-            String path = System.getProperty("josm.cache");
-            if (path != null) {
-                cacheDir = new File(path).getAbsoluteFile();
-            } else {
-                path = System.getProperty("josm.home");
-                if (path != null) {
-                    cacheDir = new File(path, "cache");
-                } else {
-                    path = get("cache.folder", null);
-                    if (path != null) {
-                        cacheDir = new File(path).getAbsoluteFile();
-                    } else {
-                        cacheDir = Main.platform.getDefaultCacheDirectory();
-                    }
-                }
-            }
-        }
-        if (createIfMissing && !cacheDir.exists() && !cacheDir.mkdirs()) {
-            Logging.warn(tr("Failed to create missing cache directory: {0}", cacheDir.getAbsoluteFile()));
-            JOptionPane.showMessageDialog(
-                    Main.parent,
-                    tr("<html>Failed to create missing cache directory: {0}</html>", cacheDir.getAbsoluteFile()),
-                    tr("Error"),
-                    JOptionPane.ERROR_MESSAGE
-            );
-        }
-        return cacheDir;
+        return dirs.getCacheDirectory(createIfMissing);
     }
 
     private static void addPossibleResourceDir(Set<String> locations, String s) {
@@ -781,8 +696,6 @@
         if (!defaults) {
             /* currently unused, but may help to fix configuration issues in future */
             putInt("josm.version", Version.getInstance().getVersion());
-
-            updateSystemProperties();
         }
 
         File backupFile = new File(prefFile + "_backup");
@@ -836,7 +749,6 @@
         reader.parse();
         settingsMap.clear();
         settingsMap.putAll(reader.getSettings());
-        updateSystemProperties();
         removeObsolete(reader.getVersion());
     }
 
@@ -983,9 +895,6 @@
      */
     public void resetToInitialState() {
         resetToDefault();
-        preferencesDir = null;
-        cacheDir = null;
-        userdataDir = null;
         saveOnPut = true;
         initSuccessful = false;
     }
@@ -1504,37 +1413,6 @@
     }
 
     /**
-     * Updates system properties with the current values in the preferences.
-     */
-    public void updateSystemProperties() {
-        if ("true".equals(get("prefer.ipv6", "auto")) && !"true".equals(Utils.updateSystemProperty("java.net.preferIPv6Addresses", "true"))) {
-            // never set this to false, only true!
-            Logging.info(tr("Try enabling IPv6 network, prefering IPv6 over IPv4 (only works on early startup)."));
-        }
-        Utils.updateSystemProperty("http.agent", Version.getInstance().getAgentString());
-        Utils.updateSystemProperty("user.language", get("language"));
-        // Workaround to fix a Java bug. This ugly hack comes from Sun bug database: https://bugs.openjdk.java.net/browse/JDK-6292739
-        // Force AWT toolkit to update its internal preferences (fix #6345).
-        // Does not work anymore with Java 9, to remove with Java 9 migration
-        if (Utils.getJavaVersion() < 9 && !GraphicsEnvironment.isHeadless()) {
-            try {
-                Field field = Toolkit.class.getDeclaredField("resources");
-                Utils.setObjectsAccessible(field);
-                field.set(null, ResourceBundle.getBundle("sun.awt.resources.awt"));
-            } catch (ReflectiveOperationException | RuntimeException e) { // NOPMD
-                // Catch RuntimeException in order to catch InaccessibleObjectException, new in Java 9
-                Logging.warn(e);
-            }
-        }
-        // Possibility to disable SNI (not by default) in case of misconfigured https servers
-        // See #9875 + http://stackoverflow.com/a/14884941/2257172
-        // then https://josm.openstreetmap.de/ticket/12152#comment:5 for details
-        if (getBoolean("jdk.tls.disableSNIExtension", false)) {
-            Utils.updateSystemProperty("jsse.enableSNIExtension", "false");
-        }
-    }
-
-    /**
      * Replies the collection of plugin site URLs from where plugin lists can be downloaded.
      * @return the collection of plugin site URLs
      * @see #getOnlinePluginSites
Index: src/org/openstreetmap/josm/data/preferences/JosmBaseDirectories.java
===================================================================
--- src/org/openstreetmap/josm/data/preferences/JosmBaseDirectories.java	(nonexistent)
+++ src/org/openstreetmap/josm/data/preferences/JosmBaseDirectories.java	(working copy)
@@ -0,0 +1,117 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.preferences;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.spi.preferences.IBaseDirectories;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ *
+ * @since xxx
+ */
+public class JosmBaseDirectories implements IBaseDirectories {
+    /**
+     * Internal storage for the preference directory.
+     */
+    private File preferencesDir;
+
+    /**
+     * Internal storage for the cache directory.
+     */
+    private File cacheDir;
+
+    /**
+     * Internal storage for the user data directory.
+     */
+    private File userdataDir;
+
+    @Override
+    public File getPreferencesDirectory(boolean createIfMissing) {
+        if (preferencesDir == null) {
+            String path;
+            path = System.getProperty("josm.pref");
+            if (path != null) {
+                preferencesDir = new File(path).getAbsoluteFile();
+            } else {
+                path = System.getProperty("josm.home");
+                if (path != null) {
+                    preferencesDir = new File(path).getAbsoluteFile();
+                } else {
+                    preferencesDir = Main.platform.getDefaultPrefDirectory();
+                }
+            }
+        }
+        if (createIfMissing && !preferencesDir.exists() && !preferencesDir.mkdirs()) {
+            Logging.warn(tr("Failed to create missing preferences directory: {0}", preferencesDir.getAbsoluteFile()));
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("<html>Failed to create missing preferences directory: {0}</html>", preferencesDir.getAbsoluteFile()),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+            );
+        }
+        return preferencesDir;
+    }
+
+    @Override
+    public File getUserDataDirectory(boolean createIfMissing) {
+        if (userdataDir == null) {
+            String path;
+            path = System.getProperty("josm.userdata");
+            if (path != null) {
+                userdataDir = new File(path).getAbsoluteFile();
+            } else {
+                path = System.getProperty("josm.home");
+                if (path != null) {
+                    userdataDir = new File(path).getAbsoluteFile();
+                } else {
+                    userdataDir = Main.platform.getDefaultUserDataDirectory();
+                }
+            }
+        }
+        if (createIfMissing && !userdataDir.exists() && !userdataDir.mkdirs()) {
+            Logging.warn(tr("Failed to create missing user data directory: {0}", userdataDir.getAbsoluteFile()));
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("<html>Failed to create missing user data directory: {0}</html>", userdataDir.getAbsoluteFile()),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+            );
+        }
+        return userdataDir;
+    }
+
+    @Override
+    public File getCacheDirectory(boolean createIfMissing) {
+        if (cacheDir == null) {
+            String path = System.getProperty("josm.cache");
+            if (path != null) {
+                cacheDir = new File(path).getAbsoluteFile();
+            } else {
+                path = System.getProperty("josm.home");
+                if (path != null) {
+                    cacheDir = new File(path, "cache");
+                } else {
+                    cacheDir = Main.platform.getDefaultCacheDirectory();
+                }
+            }
+        }
+        if (createIfMissing && !cacheDir.exists() && !cacheDir.mkdirs()) {
+            Logging.warn(tr("Failed to create missing cache directory: {0}", cacheDir.getAbsoluteFile()));
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("<html>Failed to create missing cache directory: {0}</html>", cacheDir.getAbsoluteFile()),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+            );
+        }
+        return cacheDir;
+    }
+
+}

Property changes on: src/org/openstreetmap/josm/data/preferences/JosmBaseDirectories.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplication.java	(revision 12983)
+++ src/org/openstreetmap/josm/gui/MainApplication.java	(working copy)
@@ -10,10 +10,12 @@
 import java.awt.Font;
 import java.awt.GraphicsEnvironment;
 import java.awt.GridBagLayout;
+import java.awt.Toolkit;
 import java.awt.event.KeyEvent;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Field;
 import java.net.Authenticator;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -37,6 +39,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.Callable;
@@ -147,6 +150,8 @@
 import org.openstreetmap.josm.plugins.PluginHandler;
 import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
+import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
 import org.openstreetmap.josm.tools.FontsManager;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.HttpClient;
@@ -932,7 +937,13 @@
         if (!language.isPresent()) {
             I18n.set(Config.getPref().get("language", null));
         }
-        Main.pref.updateSystemProperties();
+        updateSystemProperties();
+        Main.pref.addPreferenceChangeListener(new PreferenceChangedListener() {
+            @Override
+            public void preferenceChanged(PreferenceChangeEvent e) {
+                updateSystemProperties();
+            }
+        });
 
         checkIPv6();
 
@@ -1072,6 +1083,38 @@
     }
 
     /**
+     * Updates system properties with the current values in the preferences.
+     */
+    public static void updateSystemProperties() {
+        if ("true".equals(Config.getPref().get("prefer.ipv6", "auto"))
+                && !"true".equals(Utils.updateSystemProperty("java.net.preferIPv6Addresses", "true"))) {
+            // never set this to false, only true!
+            Logging.info(tr("Try enabling IPv6 network, prefering IPv6 over IPv4 (only works on early startup)."));
+        }
+        Utils.updateSystemProperty("http.agent", Version.getInstance().getAgentString());
+        Utils.updateSystemProperty("user.language", Config.getPref().get("language"));
+        // Workaround to fix a Java bug. This ugly hack comes from Sun bug database: https://bugs.openjdk.java.net/browse/JDK-6292739
+        // Force AWT toolkit to update its internal preferences (fix #6345).
+        // Does not work anymore with Java 9, to remove with Java 9 migration
+        if (Utils.getJavaVersion() < 9 && !GraphicsEnvironment.isHeadless()) {
+            try {
+                Field field = Toolkit.class.getDeclaredField("resources");
+                Utils.setObjectsAccessible(field);
+                field.set(null, ResourceBundle.getBundle("sun.awt.resources.awt"));
+            } catch (ReflectiveOperationException | RuntimeException e) { // NOPMD
+                // Catch RuntimeException in order to catch InaccessibleObjectException, new in Java 9
+                Logging.warn(e);
+            }
+        }
+        // Possibility to disable SNI (not by default) in case of misconfigured https servers
+        // See #9875 + http://stackoverflow.com/a/14884941/2257172
+        // then https://josm.openstreetmap.de/ticket/12152#comment:5 for details
+        if (Config.getPref().getBoolean("jdk.tls.disableSNIExtension", false)) {
+            Utils.updateSystemProperty("jsse.enableSNIExtension", "false");
+        }
+    }
+
+    /**
      * Setup the sources for NTV2 grid shift files for projection support.
      * @since 12795
      */
Index: src/org/openstreetmap/josm/plugins/Plugin.java
===================================================================
--- src/org/openstreetmap/josm/plugins/Plugin.java	(revision 13009)
+++ src/org/openstreetmap/josm/plugins/Plugin.java	(working copy)
@@ -16,6 +16,7 @@
 import java.util.List;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.MapFrameListener;
 import org.openstreetmap.josm.gui.download.DownloadSelection;
@@ -22,6 +23,7 @@
 import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.spi.preferences.IBaseDirectories;
+import org.openstreetmap.josm.spi.preferences.IPreferences;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -57,7 +59,9 @@
      */
     private PluginInformation info;
 
-    private final IBaseDirectories pluginBaseDirectories = new PluginBaseDirectories();
+    private final IBaseDirectories pluginBaseDirectories;
+    final Preferences pluginPref;
+    boolean pluginPrefInitialized;
 
     private class PluginBaseDirectories implements IBaseDirectories {
         private File preferencesDir;
@@ -108,6 +112,8 @@
      */
     public Plugin(PluginInformation info) {
         this.info = info;
+        this.pluginBaseDirectories = new PluginBaseDirectories();
+        this.pluginPref = new Preferences(pluginBaseDirectories);
     }
 
     /**
@@ -148,6 +154,16 @@
         return new File(Main.pref.getPluginsDirectory(), info.name).getPath();
     }
 
+    public IPreferences getPref() {
+        if (!pluginPrefInitialized) {
+            // lazy initialization, so it will not create directories and files
+            // when preferences is not accessed by the plugin
+            pluginPref.init(false);
+            pluginPrefInitialized = true;
+        }
+        return pluginPref;
+    }
+
     @Override
     public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {}
 
Index: src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 12983)
+++ src/org/openstreetmap/josm/plugins/PluginHandler.java	(working copy)
@@ -1554,6 +1554,20 @@
         return result;
     }
 
+    public static void shutdown() {
+        for (PluginProxy pp : pluginList) {
+            Utils.instanceOfAndCast(pp.getPlugin(), Plugin.class)
+                    .filter(plugin -> plugin.pluginPrefInitialized).ifPresent(plugin -> {
+                try {
+                    plugin.pluginPref.saveDefaults();
+                } catch (IOException ex) {
+                    Logging.log(Logging.LEVEL_WARN,
+                            tr("Failed to save default preferences for plugin {0}.", plugin.getPluginInformation().name), ex);
+                }
+            });
+        }
+    }
+
     private static class UpdatePluginsMessagePanel extends JPanel {
         private final JMultilineLabel lblMessage = new JMultilineLabel("");
         private final JCheckBox cbDontShowAgain = new JCheckBox(
