Program: 11412
Project: 11412
Buggy source:
protected void updateTiles(Axis2D axis){
  int xPix=axis.getAxisX().getSizePixels();
  if (!isVisible() || xPix <= 0) {
    return;
  }
  double minx=axis.getMinX();
  double maxx=axis.getMaxX();
  double maxy=axis.getMaxY();
  double miny=axis.getMinY();
  double[] bounds=new double[]{minx,maxx,miny,maxy};
  if (Arrays.equals(bounds,lastBounds.get())) {
    return;
  }
  lastBounds.set(bounds);
  double xTileDim=xPix / 256.;
  LatLonGeo ne=geoProj.unproject(maxx,maxy);
  LatLonGeo sw=geoProj.unproject(minx,miny);
  double east=ne.getLonDeg();
  double west=sw.getLonDeg();
  double lonSizeDeg=(east - west) / xTileDim;
  double zoomApprox=Math.log(360 / lonSizeDeg) / LOG2;
  final int zoom=(int)Math.min(Math.floor(zoomApprox),maxZoom);
  lastZoom.set(zoom);
  Vector2d tileNE=slippyProj[zoom].project(ne);
  Vector2d tileSW=slippyProj[zoom].project(sw);
  final int tileYmin=(int)Math.floor(tileNE.getY());
  final int tileYmax=(int)Math.ceil(tileSW.getY());
  final int tileXmin=(int)Math.floor(tileSW.getX());
  final int tileXmax=(int)Math.ceil(tileNE.getX());
  lock.lock();
  try {
    for (int y=tileYmin; y < tileYmax; y++) {
      for (int x=tileXmin; x < tileXmax; x++) {
        RGBTextureProjected2D tex=cache.getTextureIfPresent(zoom,x,y);
        if (tex != null && drawableTextures.containsKey(new TextureUnit<DrawableTexture>(tex))) {
          continue;
        }
        exec.submit(new FetchTexture(zoom,x,y));
      }
    }
    Iterator<TextureUnit<DrawableTexture>> itr=drawableTextures.keySet().iterator();
    while (itr.hasNext()) {
      TextureUnit<DrawableTexture> texUnit=itr.next();
      TextureProjected2D tex=(TextureProjected2D)texUnit.getTexture();
      double[] texBounds=getBounds(tex.getProjection());
      int texZoom=texZoomMap.get(tex);
      if (texZoom != zoom || !intersect(bounds,texBounds)) {
        itr.remove();
        texZoomMap.remove(tex);
      }
    }
  }
  finally {
    lock.unlock();
  }
}

Fixed version (ground truth):
protected void updateTiles(Axis2D axis){
  int xPix=axis.getAxisX().getSizePixels();
  if (!isVisible() || xPix <= 0) {
    return;
  }
  double minx=axis.getMinX();
  double maxx=axis.getMaxX();
  double maxy=axis.getMaxY();
  double miny=axis.getMinY();
  double[] bounds=new double[]{minx,maxx,miny,maxy};
  if (Arrays.equals(bounds,lastBounds.get())) {
    return;
  }
  lastBounds.set(bounds);
  double xTileDim=xPix / 256.;
  LatLonGeo ne=geoProj.unproject(maxx,maxy);
  LatLonGeo sw=geoProj.unproject(minx,miny);
  double east=ne.getLonDeg();
  double west=sw.getLonDeg();
  double lonSizeDeg=(east - west) / xTileDim;
  double zoomApprox=Math.log(360 / lonSizeDeg) / LOG2;
  final int zoom=(int)Math.min(Math.round(zoomApprox),maxZoom);
  lastZoom.set(zoom);
  Vector2d tileNE=slippyProj[zoom].project(ne);
  Vector2d tileSW=slippyProj[zoom].project(sw);
  final int tileYmin=(int)Math.floor(tileNE.getY());
  final int tileYmax=(int)Math.ceil(tileSW.getY());
  final int tileXmin=(int)Math.floor(tileSW.getX());
  final int tileXmax=(int)Math.ceil(tileNE.getX());
  lock.lock();
  try {
    for (int y=tileYmin; y < tileYmax; y++) {
      for (int x=tileXmin; x < tileXmax; x++) {
        RGBTextureProjected2D tex=cache.getTextureIfPresent(zoom,x,y);
        if (tex != null && drawableTextures.containsKey(new TextureUnit<DrawableTexture>(tex))) {
          continue;
        }
        exec.submit(new FetchTexture(zoom,x,y));
      }
    }
    Iterator<TextureUnit<DrawableTexture>> itr=drawableTextures.keySet().iterator();
    while (itr.hasNext()) {
      TextureUnit<DrawableTexture> texUnit=itr.next();
      TextureProjected2D tex=(TextureProjected2D)texUnit.getTexture();
      double[] texBounds=getBounds(tex.getProjection());
      int texZoom=texZoomMap.get(tex);
      if (texZoom != zoom || !intersect(bounds,texBounds)) {
        itr.remove();
        texZoomMap.remove(tex);
      }
    }
  }
  finally {
    lock.unlock();
  }
}