Index: trunk/src/org/openstreetmap/josm/data/osm/BBox.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/BBox.java	(revision 17751)
+++ trunk/src/org/openstreetmap/josm/data/osm/BBox.java	(revision 17752)
@@ -148,8 +148,5 @@
     public final void add(double x, double y) {
         if (!Double.isNaN(x) && !Double.isNaN(y)) {
-            xmin = Math.min(xmin, x);
-            xmax = Math.max(xmax, x);
-            ymin = Math.min(ymin, y);
-            ymax = Math.max(ymax, y);
+            set(Math.min(xmin, x), Math.max(xmax, x), Math.min(ymin, y), Math.max(ymax, y));
         }
     }
@@ -161,9 +158,13 @@
     public final void add(BBox other) {
         if (other.isValid()) {
-            xmin = Math.min(xmin, other.xmin);
-            xmax = Math.max(xmax, other.xmax);
-            ymin = Math.min(ymin, other.ymin);
-            ymax = Math.max(ymax, other.ymax);
-        }
+            set(Math.min(xmin, other.xmin), Math.max(xmax, other.xmax), Math.min(ymin, other.ymin), Math.max(ymax, other.ymax));
+        }
+    }
+
+    protected void set(double xmin, double xmax, double ymin, double ymax) {
+        this.xmin = xmin;
+        this.xmax = xmax;
+        this.ymin = ymin;
+        this.ymax = ymax;
     }
 
@@ -371,12 +372,12 @@
 
     @Override
-    public int hashCode() {
+    public final int hashCode() {
         return Objects.hash(xmin, xmax, ymin, ymax);
     }
 
     @Override
-    public boolean equals(Object o) {
+    public final boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (!(o instanceof BBox)) return false;
         BBox b = (BBox) o;
         return Double.compare(b.xmax, xmax) == 0 && Double.compare(b.ymax, ymax) == 0
@@ -451,3 +452,28 @@
                 LatLon.cDdFormatter.format(ymax));
     }
+
+    /**
+     * Returns an immutable version of this bbox, i.e., modifying calls throw an {@link UnsupportedOperationException}.
+     * @return an immutable version of this bbox
+     */
+    BBox toImmutable() {
+        return new Immutable(this);
+    }
+
+    private static class Immutable extends BBox {
+
+        Immutable(BBox copy) {
+            super(copy);
+        }
+
+        @Override
+        protected void set(double xmin, double xmax, double ymin, double ymax) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        BBox toImmutable() {
+            return this;
+        }
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/IPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/IPrimitive.java	(revision 17751)
+++ trunk/src/org/openstreetmap/josm/data/osm/IPrimitive.java	(revision 17752)
@@ -466,4 +466,5 @@
     /**
      * Fetches the bounding box of the primitive.
+     * Since 17752, the returned bounding box might be immutable, i.e., modifying calls throw an {@link UnsupportedOperationException}.
      * @return Bounding box of the object
      * @since 13764
Index: trunk/src/org/openstreetmap/josm/data/osm/Relation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 17751)
+++ trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 17752)
@@ -441,16 +441,19 @@
     @Override
     public BBox getBBox() {
-        if (getDataSet() != null && bbox != null)
-            return new BBox(bbox); // use cached value
+        if (getDataSet() != null && bbox != null) {
+            return this.bbox; // use cached immutable value
+        }
 
         BBox box = new BBox();
         addToBBox(box, new HashSet<PrimitiveId>());
-        if (getDataSet() != null)
-            setBBox(box); // set cache
-        return new BBox(box);
+        if (getDataSet() == null) {
+            return box;
+        }
+        setBBox(box); // set cached immutable value
+        return this.bbox;
     }
 
     private void setBBox(BBox bbox) {
-        this.bbox = bbox;
+        this.bbox = bbox == null ? null : bbox.toImmutable();
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 17751)
+++ trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 17752)
@@ -586,7 +586,7 @@
             return new BBox(this);
         if (bbox == null) {
-            bbox = new BBox(this);
-        }
-        return new BBox(bbox);
+            setBBox(new BBox(this));
+        }
+        return bbox;
     }
 
@@ -596,7 +596,11 @@
     }
 
+    private void setBBox(BBox bbox) {
+        this.bbox = bbox == null ? null : bbox.toImmutable();
+    }
+
     @Override
     public void updatePosition() {
-        bbox = new BBox(this);
+        setBBox(new BBox(this));
         clearCachedStyle();
     }
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadTextComponentValidator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadTextComponentValidator.java	(revision 17751)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadTextComponentValidator.java	(revision 17752)
@@ -154,9 +154,8 @@
             this.area = primitives.stream()
                     .map(IPrimitive::getBBox)
-                    .reduce((b1, b2) -> {
+                    .reduce(new BBox(), (b1, b2) -> {
                         b1.add(b2);
                         return b1;
-                    }).map(BBox::area)
-                    .orElse(Double.NaN);
+                    }).area();
             validate();
         }
