Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java	(revision 35964)
@@ -6,7 +6,9 @@
 import java.util.GregorianCalendar;
 import java.util.List;
+import java.util.Optional;
 
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.SystemOfMeasurement;
+import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.gpx.WayPoint;
@@ -34,7 +36,4 @@
 
     private static GeoidCorrectionKind geoidKind = GeoidCorrectionKind.None;
-
-    /** The HGT reader instance. */
-    private static final HgtReader hgt = new HgtReader();
 
     /**
@@ -166,9 +165,9 @@
      *         not height attribute.
      */
-    public static double getSrtmElevation(LatLon ll) {
+    public static double getSrtmElevation(ILatLon ll) {
         if (ll != null) {
             // Try to read data from SRTM file
             // TODO: Option to switch this off
-            double eleHgt = hgt.getElevationFromHgt(ll);
+            double eleHgt = HgtReader.getElevationFromHgt(ll);
 
             if (isValidElevation(eleHgt)) {
@@ -177,4 +176,16 @@
         }
         return NO_ELEVATION;
+    }
+
+    /**
+     * Get the bounds for the pixel elevation for the latitude
+     * @param location The location to get
+     * @return The bounds for the elevation area
+     */
+    public static Optional<Bounds> getBounds(ILatLon location) {
+        if (location != null) {
+            return HgtReader.getBounds(location);
+        }
+        return Optional.empty();
     }
 
@@ -252,5 +263,5 @@
 
         Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
-        calendar.setTime(wpt.getDate());   // assigns calendar to given date
+        calendar.setTimeInMillis(wpt.getTimeInMillis()); // assigns calendar to given date
         return calendar.get(Calendar.HOUR_OF_DAY);
     }
@@ -263,5 +274,5 @@
 
         Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
-        calendar.setTime(wpt.getDate());   // assigns calendar to given date
+        calendar.setTimeInMillis(wpt.getTimeInMillis()); // assigns calendar to given date
         return calendar.get(Calendar.MINUTE);
     }
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java	(revision 35964)
@@ -6,4 +6,5 @@
 import java.awt.Color;
 
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
 import org.openstreetmap.josm.gui.IconToggleButton;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -33,4 +34,5 @@
 
         createColorMaps();
+        ExtensionFileFilter.addImporter(new HgtFileImporter());
 
         // TODO: Disable this view as long as it is not stable
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java	(revision 35964)
@@ -3,14 +3,23 @@
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-import java.nio.channels.FileChannel;
+import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.HashMap;
-
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.compress.utils.IOUtils;
+import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.io.Compression;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Logging;
@@ -23,16 +32,15 @@
  */
 public class HgtReader {
-    private static final int SECONDS_PER_MINUTE = 60;
+    private static final int SRTM_EXTENT = 1; // degree
+    private static final List<String> COMPRESSION_EXT = Arrays.asList("xz", "gzip", "zip", "bz", "bz2");
 
     public static final String HGT_EXT = ".hgt";
 
     // alter these values for different SRTM resolutions
-    public static final int HGT_RES = 3; // resolution in arc seconds
-    public static final int HGT_ROW_LENGTH = 1201; // number of elevation values per line
-    public static final int HGT_VOID = -32768; // magic number which indicates 'void data' in HGT file
-
-    private final HashMap<String, ShortBuffer> cache = new HashMap<>();
-
-    public double getElevationFromHgt(LatLon coor) {
+    public static final int HGT_VOID = Short.MIN_VALUE; // magic number which indicates 'void data' in HGT file
+
+    private static final HashMap<String, short[][]> cache = new HashMap<>();
+
+    public static double getElevationFromHgt(ILatLon coor) {
         try {
             String file = getHgtFileName(coor);
@@ -48,9 +56,12 @@
                     String fullPath = new File(location + File.separator + "elevation", file).getPath();
                     File f = new File(fullPath);
+                    if (!f.exists()) {
+                        for (String ext : COMPRESSION_EXT) {
+                            f = new File(fullPath + "." + ext);
+                            if (f.exists()) break;
+                        }
+                    }
                     if (f.exists()) {
-                        // found something: read HGT file...
-                        ShortBuffer data = readHgtFile(fullPath);
-                        // ... and store result in cache
-                        cache.put(file, data);
+                        read(f);
                         break;
                     }
@@ -59,5 +70,5 @@
 
             // read elevation value
-            return readElevation(coor);
+            return readElevation(coor, file);
         } catch (FileNotFoundException e) {
             Logging.error("Get elevation from HGT " + coor + " failed: => " + e.getMessage());
@@ -72,25 +83,47 @@
     }
 
-    @SuppressWarnings("resource")
-    private ShortBuffer readHgtFile(String file) throws Exception {
+    public static Bounds read(File file) throws FileNotFoundException, IOException {
+        String location = file.getName();
+        for (String ext : COMPRESSION_EXT) {
+            location = location.replaceAll("\\." + ext + "$", "");
+        }
+        short[][] sb = readHgtFile(file.getPath());
+        // Overwrite the cache file (assume that is desired)
+        cache.put(location, sb);
+        Pattern pattern = Pattern.compile("(N|S)([0-9]{2})(E|W)([0-9]{3})");
+        Matcher matcher = pattern.matcher(location);
+        if (matcher.lookingAt()) {
+            int lat = (matcher.group(1) == "S" ? -1 : 1) * Integer.parseInt(matcher.group(2));
+            int lon = (matcher.group(3) == "W" ? -1 : 1) * Integer.parseInt(matcher.group(4));
+            return new Bounds(lat, lon, lat + 1, lon + 1);
+        }
+        return null;
+    }
+
+    private static short[][] readHgtFile(String file) throws FileNotFoundException, IOException {
         CheckParameterUtil.ensureParameterNotNull(file);
 
-        FileChannel fc = null;
-        ShortBuffer sb = null;
-        try {
-            // Eclipse complains here about resource leak on 'fc' - even with 'finally' clause???
-            fc = new FileInputStream(file).getChannel();
+        short[][] data = null;
+
+        try (InputStream fis = Compression.getUncompressedFileInputStream(Paths.get(file))) {
             // choose the right endianness
-
-            ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size());
-            while (bb.remaining() > 0) fc.read(bb);
-
-            bb.flip();
-            sb = bb.order(ByteOrder.BIG_ENDIAN).asShortBuffer();
-        } finally {
-            if (fc != null) fc.close();
-        }
-
-        return sb;
+            ByteBuffer bb = ByteBuffer.wrap(IOUtils.toByteArray(fis));
+            //System.out.println(Arrays.toString(bb.array()));
+            bb.order(ByteOrder.BIG_ENDIAN);
+            int size = (int) Math.sqrt(bb.array().length / 2);
+            data = new short[size][size];
+            int x = 0;
+            int y = 0;
+            while (x < size) {
+                while (y < size) {
+                    data[x][y] = bb.getShort(2 * (x * size + y));
+                    y++;
+                }
+                x++;
+                y = 0;
+            }
+        }
+
+        return data;
     }
 
@@ -102,8 +135,20 @@
      * @return the elevation value or <code>Double.NaN</code>, if no value is present
      */
-    public double readElevation(LatLon coor) {
+    public static double readElevation(LatLon coor) {
         String tag = getHgtFileName(coor);
-
-        ShortBuffer sb = cache.get(tag);
+        return readElevation(coor, tag);
+    }
+
+    /**
+     * Reads the elevation value for the given coordinate.
+     *
+     * See also <a href="http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file">stackexchange.com</a>
+     * @param coor the coordinate to get the elevation data for
+     * @param fileName The expected filename
+     * @return the elevation value or <code>Double.NaN</code>, if no value is present
+     */
+    public static double readElevation(ILatLon coor, String fileName) {
+
+        short[][] sb = cache.get(fileName);
 
         if (sb == null) {
@@ -111,27 +156,65 @@
         }
 
-        // see http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file
-        double fLat = frac(coor.lat()) * SECONDS_PER_MINUTE;
-        double fLon = frac(coor.lon()) * SECONDS_PER_MINUTE;
-
-        // compute offset within HGT file
-        int row = (int) Math.round(fLat * SECONDS_PER_MINUTE / HGT_RES);
-        int col = (int) Math.round(fLon * SECONDS_PER_MINUTE / HGT_RES);
-
-        row = HGT_ROW_LENGTH - row;
-        int cell = (HGT_ROW_LENGTH * (row - 1)) + col;
-
-        // valid position in buffer?
-        if (cell < sb.limit()) {
-            short ele = sb.get(cell);
-            // check for data voids
-            if (ele == HGT_VOID) {
-                return ElevationHelper.NO_ELEVATION;
-            } else {
-                return ele;
-            }
-        } else {
-            return ElevationHelper.NO_ELEVATION;
-        }
+        int[] index = getIndex(coor, sb.length);
+        short ele = sb[index[0]][index[1]];
+
+        if (ele == HGT_VOID) {
+            return ElevationHelper.NO_ELEVATION;
+        }
+        return ele;
+    }
+
+    public static Optional<Bounds> getBounds(ILatLon location) {
+        final String fileName = getHgtFileName(location);
+        final short[][] sb = cache.get(fileName);
+
+        if (sb == null) {
+            return Optional.empty();
+        }
+
+        final double latDegrees = location.lat();
+        final double lonDegrees = location.lon();
+
+        final float fraction = ((float) SRTM_EXTENT) / sb.length;
+        final int latitude = (int) Math.floor(latDegrees) + (latDegrees < 0 ? 1 : 0);
+        final int longitude = (int) Math.floor(lonDegrees) + (lonDegrees < 0 ? 1 : 0);
+
+        final int[] index = getIndex(location, sb.length);
+        final int latSign = latitude > 0 ? 1 : -1;
+        final int lonSign = longitude > 0 ? 1 : -1;
+        final double minLat = latitude + latSign * fraction * index[0];
+        final double maxLat = latitude + latSign * fraction * (index[0] + 1);
+        final double minLon = longitude + lonSign * fraction * index[1];
+        final double maxLon = longitude + lonSign * fraction * (index[1] + 1);
+        return Optional.of(new Bounds(Math.min(minLat, maxLat), Math.min(minLon, maxLon),
+                Math.max(minLat, maxLat), Math.max(minLon, maxLon)));
+    }
+
+    /**
+     * Get the index to use for a short[latitude][longitude] = height in meters array
+     *
+     * @param latLon
+     *            The location to get the index for
+     * @param mapSize
+     *            The size of the map
+     * @return A [latitude, longitude] = int (index) array.
+     */
+    private static int[] getIndex(ILatLon latLon, int mapSize)
+    {
+        double latDegrees = latLon.lat();
+        double lonDegrees = latLon.lon();
+
+        float fraction = ((float) SRTM_EXTENT) / mapSize;
+        int latitude = (int) Math.floor(Math.abs(latDegrees - (int) latDegrees) / fraction);
+        int longitude = (int) Math.floor(Math.abs(lonDegrees - (int) lonDegrees) / fraction);
+        if (latDegrees >= 0)
+        {
+            latitude = mapSize - 1 - latitude;
+        }
+        if (lonDegrees < 0)
+        {
+            longitude = mapSize - 1 - longitude;
+        }
+        return new int[] { latitude, longitude };
     }
 
@@ -144,17 +227,21 @@
      * @return the file name of the HGT file
      */
-    public String getHgtFileName(LatLon latLon) {
-        int lat = (int) latLon.lat();
-        int lon = (int) latLon.lon();
+    public static String getHgtFileName(ILatLon latLon) {
+        int lat = (int) Math.floor(latLon.lat());
+        int lon = (int) Math.floor(latLon.lon());
 
         String latPref = "N";
-        if (lat < 0) latPref = "S";
+        if (lat < 0) {
+            latPref = "S";
+            lat = Math.abs(lat);
+        }
 
         String lonPref = "E";
         if (lon < 0) {
             lonPref = "W";
-        }
-
-        return String.format("%s%02d%s%03d%s", latPref, lat, lonPref, lon, HGT_EXT);
+            lon = Math.abs(lon);
+        }
+
+        return latPref + lat + lonPref + lon + HGT_EXT;
     }
 
@@ -168,3 +255,7 @@
         return fPart;
     }
+
+    public static void clearCache() {
+        cache.clear();
+    }
 }
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationProfile.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationProfile.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationProfile.java	(revision 35964)
@@ -2,5 +2,5 @@
 package org.openstreetmap.josm.plugins.elevation;
 
-import java.util.Date;
+import java.time.Instant;
 import java.util.List;
 
@@ -21,10 +21,10 @@
      * Gets the time stamp of first recorded track point.
      */
-    Date getStart();
+    Instant getStart();
 
     /**
      * Gets the time stamp of last recorded track point.
      */
-    Date getEnd();
+    Instant getEnd();
 
     /**
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java	(revision 35964)
@@ -28,4 +28,7 @@
             currentLayer = new ElevationGridLayer(tr("Elevation Grid")); // TODO: Better name
             MainApplication.getLayerManager().addLayer(currentLayer);
+        } else if (!MainApplication.getLayerManager().containsLayer(currentLayer)) {
+            currentLayer = null;
+            actionPerformed(arg0);
         }
     }
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java	(revision 35964)
@@ -2,6 +2,6 @@
 package org.openstreetmap.josm.plugins.elevation.gpx;
 
+import java.time.Instant;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 
@@ -45,6 +45,6 @@
     private int avrgHeight;
     private double dist;
-    private Date start = new Date();
-    private Date end = new Date();
+    private Instant start;
+    private Instant end;
     private final WayPoint[] importantWayPoints = new WayPoint[4];
     private IElevationProfile parent;
@@ -121,6 +121,6 @@
             return;
 
-        start = new Date(0L);
-        end = new Date();
+        start = Instant.EPOCH;
+        end = Instant.now();
         this.minHeight = Integer.MAX_VALUE;
         this.maxHeight = Integer.MIN_VALUE;
@@ -196,6 +196,6 @@
     protected void setStart(WayPoint wp) {
         importantWayPoints[WAYPOINT_START] = wp;
-        if(wp.getDate() != null)
-            this.start = wp.getDate();
+        if(wp.getInstant() != null)
+            this.start = wp.getInstant();
     }
 
@@ -205,6 +205,6 @@
     protected void setEnd(WayPoint wp) {
         importantWayPoints[WAYPOINT_END] = wp;
-        if(wp.getDate() != null)
-            this.end = wp.getDate();
+        if(wp.getInstant() != null)
+            this.end = wp.getInstant();
     }
 
@@ -257,5 +257,5 @@
 
     @Override
-    public Date getEnd() {
+    public Instant getEnd() {
         return end;
     }
@@ -308,8 +308,8 @@
 
         if (wp1 != null && wp2 != null) {
-            Date wp1Date = wp1.getDate();
-            Date wp2Date = wp2.getDate();
+            Instant wp1Date = wp1.getInstant();
+            Instant wp2Date = wp2.getInstant();
             if (wp1Date != null && wp2Date != null) {
-                return wp2Date.getTime() - wp1Date.getTime();
+                return wp2Date.toEpochMilli() - wp1Date.toEpochMilli();
             } else {
                 Logging.warn("Waypoints without date: " + wp1 + " / " + wp2);
@@ -326,5 +326,5 @@
 
     @Override
-    public Date getStart() {
+    public Instant getStart() {
         return start;
     }
@@ -390,9 +390,9 @@
 
         if (wp.hasDate()) {
-            if (wp.getDate().after(end)) {
+            if (wp.getInstant().isAfter(this.end)) {
                 setEnd(wp);
             }
 
-            if (wp.getDate().before(start)) {
+            if (wp.getInstant().isBefore(start)) {
                 setStart(wp);
             }
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java	(revision 35964)
@@ -8,8 +8,12 @@
 import java.awt.Graphics2D;
 import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
 
 import javax.swing.Action;
 import javax.swing.Icon;
 
+import org.apache.commons.jcs3.JCS;
 import org.openstreetmap.gui.jmapviewer.MemoryTileCache;
 import org.openstreetmap.gui.jmapviewer.Tile;
@@ -19,9 +23,17 @@
 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.imagery.CoordinateConversion;
+import org.openstreetmap.josm.data.imagery.TileJobOptions;
+import org.openstreetmap.josm.data.osm.BBox;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.Notification;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+import org.openstreetmap.josm.plugins.elevation.HgtReader;
 import org.openstreetmap.josm.plugins.elevation.IVertexRenderer;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -32,5 +44,5 @@
  *
  */
-public class ElevationGridLayer extends Layer implements TileLoaderListener {
+public class ElevationGridLayer extends Layer implements TileLoaderListener, MouseListener {
     private static final int ELE_ZOOM_LEVEL = 13;
     private final IVertexRenderer vertexRenderer;
@@ -40,4 +52,6 @@
     protected TileController tileController;
 
+    private ILatLon clickLocation;
+
     private Bounds lastBounds;
     private TileSet tileSet;
@@ -45,4 +59,6 @@
     public ElevationGridLayer(String name) {
         super(name);
+        HgtReader.clearCache();
+        MainApplication.getMap().mapView.addMouseListener(this);
 
         setOpacity(0.8);
@@ -53,5 +69,5 @@
         tileCache.setCacheSize(500);
         tileSource = new ElevationGridTileSource(name);
-        tileLoader = new ElevationGridTileLoader(this);
+        tileLoader = new ElevationGridTileLoader(this, JCS.getInstance("elevationgridlayer"), new TileJobOptions(20, 20, null, 3600));
         tileController = new ElevationGridTileController(tileSource, tileCache, this, tileLoader);
     }
@@ -90,4 +106,14 @@
             }
         }
+        // Paint the current point area
+        ElevationHelper.getBounds(this.clickLocation).ifPresent(bounds -> {
+            final BBox bbox = bounds.toBBox();
+            final Point upperLeft = mv.getPoint(bbox.getTopLeft());
+            final Point bottomRight = mv.getPoint(bbox.getBottomRight());
+            final Rectangle rectangle = new Rectangle(upperLeft.x, upperLeft.y,
+                    bottomRight.x - upperLeft.x, bottomRight.y - upperLeft.y);
+            g.setColor(Color.RED);
+            g.draw(rectangle);
+        });
     }
 
@@ -150,4 +176,36 @@
         g.setColor(oldColor);
         g.drawString(text, x, y);
+    }
+
+    @Override
+    public void mouseClicked(MouseEvent e) {
+        if (e.getButton() == MouseEvent.BUTTON1) {
+            this.clickLocation = MainApplication.getMap().mapView.getLatLon(e.getX(), e.getY());
+            final double elevation = ElevationHelper.getSrtmElevation(clickLocation);
+            Notification notification = new Notification("Elevation is: " + elevation);
+            notification.setDuration(Notification.TIME_SHORT);
+            GuiHelper.runInEDT(notification::show);
+            GuiHelper.runInEDT(this::invalidate);
+        }
+    }
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+        // Do nothing
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+        // Do nothing
+    }
+
+    @Override
+    public void mouseEntered(MouseEvent e) {
+        // Do nothing
+    }
+
+    @Override
+    public void mouseExited(MouseEvent e) {
+        // Do nothing
     }
 
@@ -224,3 +282,10 @@
         }
     }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+        HgtReader.clearCache();
+        MainApplication.getMap().mapView.removeMouseListener(this);
+    }
 }
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java	(revision 35964)
@@ -10,5 +10,4 @@
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
 import java.util.concurrent.BlockingDeque;
 import java.util.concurrent.LinkedBlockingDeque;
@@ -55,5 +54,4 @@
     /**
      * Paints the vertices of this tile.
-     *
      * @param g the graphics context
      * @param mv the map view
@@ -67,5 +65,4 @@
             Point p2 = mv.getPoint(eleVertex.get(2));
             Triangle shape = new Triangle(p0, p1, p2);
-
             // obtain vertex color
             g.setColor(vertexRenderer.getElevationColor(eleVertex));
@@ -83,5 +80,5 @@
         // We abuse the loadImage method to render the vertices...
         //
-        while (toDo.size() > 0) {
+        while (!toDo.isEmpty()) {
             EleVertex vertex = toDo.poll();
 
@@ -89,8 +86,5 @@
                 vertices.add(vertex);
             } else {
-                List<EleVertex> newV = vertex.divide();
-                for (EleVertex eleVertex : newV) {
-                    toDo.add(eleVertex);
-                }
+                toDo.addAll(vertex.divide());
             }
         }
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java	(revision 35964)
@@ -2,8 +2,18 @@
 package org.openstreetmap.josm.plugins.elevation.grid;
 
+import java.io.IOException;
+import java.net.URL;
+import java.util.Optional;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.apache.commons.jcs3.access.behavior.ICacheAccess;
 import org.openstreetmap.gui.jmapviewer.Tile;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
-import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
+import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
+import org.openstreetmap.josm.data.cache.JCSCachedTileLoaderJob;
+import org.openstreetmap.josm.data.imagery.TMSCachedTileLoader;
+import org.openstreetmap.josm.data.imagery.TileJobOptions;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
@@ -12,10 +22,79 @@
  *
  */
-public class ElevationGridTileLoader implements TileLoader {
-    protected TileLoaderListener listener;
+public class ElevationGridTileLoader extends TMSCachedTileLoader {
 
-    public ElevationGridTileLoader(TileLoaderListener listener) {
-        CheckParameterUtil.ensureParameterNotNull(listener);
-        this.listener = listener;
+    class ElevationGridTileJob extends JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> implements TileJob {
+
+        private final Tile tile;
+        private final TileLoaderListener listener;
+        private final ICacheAccess<String, BufferedImageCacheEntry> cache;
+
+        protected ElevationGridTileJob(TileLoaderListener listener, Tile tile, ICacheAccess<String, BufferedImageCacheEntry> cache, TileJobOptions options,
+                ThreadPoolExecutor downloadJobExecutor) {
+            super(cache, options, downloadJobExecutor);
+            this.cache = cache;
+            this.tile = tile;
+            this.listener = listener;
+        }
+
+        @Override
+        public void run() {
+            synchronized (tile) {
+                if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading())
+                    return;
+                tile.initLoading();
+            }
+            try {
+                tile.loadImage(null);
+                tile.setLoaded(true);
+                listener.tileLoadingFinished(tile, true);
+            } catch (Exception e) {
+                tile.setError(e.getMessage());
+                listener.tileLoadingFinished(tile, false);
+            } finally {
+                tile.finishLoading();
+            }
+        }
+
+        @Override
+        public void submit() {
+            run();
+        }
+
+        @Override
+        public void submit(boolean force) {
+            submit();
+        }
+
+        @Override
+        public String getCacheKey() {
+            if (tile != null) {
+                TileSource tileSource = tile.getTileSource();
+                return Optional.ofNullable(tileSource.getName()).orElse("").replace(':', '_') + ':'
+                        + tileSource.getTileId(tile.getZoom(), tile.getXtile(), tile.getYtile());
+            }
+            return null;
+        }
+
+        @Override
+        public URL getUrl() throws IOException {
+            return new URL(String.format("http://localhost/elevation/%d/%d", tile.getTileXY().getXIndex(), tile.getTileXY().getYIndex()));
+        }
+
+        @Override
+        protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
+            return new BufferedImageCacheEntry(content);
+        }
+    }
+
+    /**
+     * Constructor
+     * @param listener          called when tile loading has finished
+     * @param cache             of the cache
+     * @param options           tile job options
+     */
+    public ElevationGridTileLoader(TileLoaderListener listener, ICacheAccess<String, BufferedImageCacheEntry> cache,
+           TileJobOptions options) {
+        super(listener, cache, options);
     }
 
@@ -24,35 +103,9 @@
         CheckParameterUtil.ensureParameterNotNull(tile);
 
-        return new TileJob() {
-
-            @Override
-            public void run() {
-                synchronized (tile) {
-                    if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading())
-                        return;
-                    tile.initLoading();
-                }
-                try {
-                    tile.loadImage(null);
-                    tile.setLoaded(true);
-                    listener.tileLoadingFinished(tile, true);
-                } catch (Exception e) {
-                    tile.setError(e.getMessage());
-                    listener.tileLoadingFinished(tile, false);
-                } finally {
-                    tile.finishLoading();
-                }
-            }
-
-            @Override
-            public void submit() {
-                run();
-            }
-
-            @Override
-            public void submit(boolean force) {
-                submit();
-            }
-        };
+        return new ElevationGridTileJob(listener,
+                tile,
+                cache,
+                options,
+                getDownloadExecutor());
     }
 
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java	(revision 35963)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java	(revision 35964)
@@ -16,6 +16,6 @@
 import java.text.Format;
 import java.text.SimpleDateFormat;
+import java.time.Instant;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 
@@ -254,8 +254,7 @@
      * Formats the date in a predefined manner: "21. Oct 2010, 12:10".
      */
-    private String formatDate(Date date) {
+    private String formatDate(Instant date) {
         Format formatter = new SimpleDateFormat("d MMM yy, HH:mm");
-
-        return formatter.format(date);
+        return formatter.format(date.toEpochMilli());
     }
 
