commit 097ff20c6e217cde9dfb06eed0b24eff5830a2b7
Author: Simon Legner <Simon.Legner@gmail.com>
Date:   2020-02-22 17:04:04 +0100

    see #18749 - Intern strings to reduce memory footprint

diff --git a/src/com/kitfox/svg/SVGElement.java b/src/com/kitfox/svg/SVGElement.java
index e41c31193..70fa9db1f 100644
--- a/src/com/kitfox/svg/SVGElement.java
+++ b/src/com/kitfox/svg/SVGElement.java
@@ -259,11 +259,12 @@ public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElem
         this.id = attrs.getValue("id");
         if (this.id != null && !this.id.equals(""))
         {
+            this.id = this.id.intern();
             diagram.setElement(this.id, this);
         }
 
         String className = attrs.getValue("class");
-        this.cssClass = (className == null || className.equals("")) ? null : className;
+        this.cssClass = (className == null || className.equals("")) ? null : className.intern();
         //docRoot = helper.docRoot;
         //universe = helper.universe;
 
diff --git a/src/com/kitfox/svg/xml/StyleAttribute.java b/src/com/kitfox/svg/xml/StyleAttribute.java
index 6e8f0f985..2dd98c6cd 100644
--- a/src/com/kitfox/svg/xml/StyleAttribute.java
+++ b/src/com/kitfox/svg/xml/StyleAttribute.java
@@ -69,14 +69,13 @@ public StyleAttribute()
     
     public StyleAttribute(String name) 
     {
-        this.name = name;
-        stringValue = null;
+        this(name, null);
     }
 
     public StyleAttribute(String name, String stringValue) 
     {
-        this.name = name;
-        this.stringValue = stringValue;
+        setName(name);
+        setStringValue(stringValue);
     }
 
     public String getName() {
@@ -85,7 +84,7 @@ public String getName() {
     
     public StyleAttribute setName(String name)
     {
-        this.name = name;
+        this.name = name == null ? null : name.intern();
         return this;
     }
     
@@ -101,7 +100,7 @@ public String getStringValue()
 
     public void setStringValue(String value)
     {
-        stringValue = value;
+        stringValue = value == null ? null : value.intern();
     }
 
     public boolean getBooleanValue() {
diff --git a/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java b/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
index 50cfb87ed..9295987a1 100644
--- a/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
+++ b/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
@@ -396,7 +396,7 @@ public ImageryPreferenceEntry(ImageryInfo i) {
             max_zoom = i.defaultMaxZoom;
             min_zoom = i.defaultMinZoom;
             cookies = i.cookies;
-            icon = i.icon;
+            icon = i.icon == null ? null : i.icon.intern();
             description = i.description;
             category = i.category != null ? i.category.getCategoryString() : null;
             if (i.bounds != null) {
@@ -567,7 +567,7 @@ public ImageryInfo(ImageryPreferenceEntry e) {
         termsOfUseText = e.terms_of_use_text;
         termsOfUseURL = e.terms_of_use_url;
         countryCode = e.country_code;
-        icon = e.icon;
+        icon = e.icon == null ? null : e.icon.intern();
         if (e.noTileHeaders != null) {
             noTileHeaders = e.noTileHeaders.toMap();
         }
@@ -632,7 +632,7 @@ public ImageryInfo(ImageryInfo i) {
         this.bestMarked = i.bestMarked;
         this.overlay = i.overlay;
         // do not copy field {@code mirrors}
-        this.icon = i.icon;
+        this.icon = i.icon == null ? null : i.icon.intern();
         this.isGeoreferenceValid = i.isGeoreferenceValid;
         this.defaultLayers = i.defaultLayers;
         this.customHttpHeaders = i.customHttpHeaders;
@@ -1189,7 +1189,7 @@ public String getIcon() {
      * @param icon The entry icon
      */
     public void setIcon(String icon) {
-        this.icon = icon;
+        this.icon = icon == null ? null : icon.intern();
     }
 
     /**
diff --git a/src/org/openstreetmap/josm/data/projection/Projections.java b/src/org/openstreetmap/josm/data/projection/Projections.java
index a4bb31f9e..fbb9c03f8 100644
--- a/src/org/openstreetmap/josm/data/projection/Projections.java
+++ b/src/org/openstreetmap/josm/data/projection/Projections.java
@@ -76,9 +76,9 @@
          * @param definition projection definition (EPSG format)
          */
         public ProjectionDefinition(String code, String name, String definition) {
-            this.code = code;
-            this.name = name;
-            this.definition = definition;
+            this.code = code.intern();
+            this.name = name.intern();
+            this.definition = definition.intern();
         }
     }
 
diff --git a/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java b/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
index b5028bc71..0c2ab9ffc 100644
--- a/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
+++ b/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
@@ -330,7 +330,8 @@ static TagCheck ofMapCSSRule(final GroupedMapCSSRule rule) throws IllegalDataExc
                     }
                     try {
                         final String val = ai.val instanceof Expression
-                                ? Optional.ofNullable(((Expression) ai.val).evaluate(new Environment())).map(Object::toString).orElse(null)
+                                ? Optional.ofNullable(((Expression) ai.val).evaluate(new Environment()))
+                                        .map(Object::toString).map(String::intern).orElse(null)
                                 : ai.val instanceof String
                                 ? (String) ai.val
                                 : ai.val instanceof Keyword
diff --git a/src/org/openstreetmap/josm/gui/mappaint/Keyword.java b/src/org/openstreetmap/josm/gui/mappaint/Keyword.java
index 3cddda625..4dd9197d4 100644
--- a/src/org/openstreetmap/josm/gui/mappaint/Keyword.java
+++ b/src/org/openstreetmap/josm/gui/mappaint/Keyword.java
@@ -23,7 +23,7 @@
      * @param val The string value that is written in the MapCSS file
      */
     public Keyword(String val) {
-        this.val = val.toLowerCase(Locale.ENGLISH);
+        this.val = val.toLowerCase(Locale.ENGLISH).intern();
     }
 
     @Override
diff --git a/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java b/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
index f5d4b98d4..8b8addbc7 100644
--- a/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
+++ b/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
@@ -95,7 +95,7 @@ private MapPaintStyles() {
          * @param key The tag name
          */
         public TagKeyReference(String key) {
-            this.key = key;
+            this.key = key.intern();
         }
 
         @Override
diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
index 793b85eaa..0647da838 100644
--- a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
+++ b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
@@ -51,7 +51,7 @@ public String toString() {
         public final boolean isSetInstruction;
 
         public AssignmentInstruction(String key, Object val, boolean isSetInstruction) {
-            this.key = key;
+            this.key = key.intern();
             this.isSetInstruction = isSetInstruction;
             if (val instanceof LiteralExpression) {
                 Object litValue = ((LiteralExpression) val).evaluate(null);
diff --git a/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java b/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
index d3d3c2c73..b967dbcee 100644
--- a/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
+++ b/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
@@ -484,13 +484,15 @@ private void initListEntriesFromAttributes() {
         final List<PresetListEntry> entries = new ArrayList<>(valueArray.length);
         for (int i = 0; i < valueArray.length; i++) {
             final PresetListEntry e = new PresetListEntry(valueArray[i]);
-            e.locale_display_value = locale_display_values != null || values_no_i18n
+            final String value = locale_display_values != null || values_no_i18n
                     ? displayArray[i]
                     : trc(values_context, fixPresetString(displayArray[i]));
+            e.locale_display_value = value == null ? null : value.intern();
             if (shortDescriptionsArray != null) {
-                e.locale_short_description = locale_short_descriptions != null
+                final String description = locale_short_descriptions != null
                         ? shortDescriptionsArray[i]
                         : tr(fixPresetString(shortDescriptionsArray[i]));
+                e.locale_short_description = description == null ? null : description.intern();
             }
 
             entries.add(e);
diff --git a/src/org/openstreetmap/josm/tools/XmlObjectParser.java b/src/org/openstreetmap/josm/tools/XmlObjectParser.java
index 89c8b3eaa..05c6058ce 100644
--- a/src/org/openstreetmap/josm/tools/XmlObjectParser.java
+++ b/src/org/openstreetmap/josm/tools/XmlObjectParser.java
@@ -137,6 +137,9 @@ else if (Double.class.equals(klass))
         }
 
         private void setValue(Entry entry, String fieldName, String value) throws SAXException {
+            if (value != null) {
+                value = value.intern();
+            }
             CheckParameterUtil.ensureParameterNotNull(entry, "entry");
             if ("class".equals(fieldName) || "default".equals(fieldName) || "throw".equals(fieldName) ||
                     "new".equals(fieldName) || "null".equals(fieldName)) {
