Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 9659)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 9660)
@@ -11,4 +11,5 @@
 import java.awt.FlowLayout;
 import java.awt.Graphics;
+import java.awt.GraphicsEnvironment;
 import java.awt.GridBagLayout;
 import java.awt.GridLayout;
@@ -382,6 +383,8 @@
         this.setVisible(true);
         titleBar.setVisible(false);
-        detachedDialog = new DetachedDialog();
-        detachedDialog.setVisible(true);
+        if (!GraphicsEnvironment.isHeadless()) {
+            detachedDialog = new DetachedDialog();
+            detachedDialog.setVisible(true);
+        }
         setIsShowing(true);
         setIsDocked(false);
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 9659)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 9660)
@@ -9,4 +9,5 @@
 import java.awt.Dimension;
 import java.awt.FlowLayout;
+import java.awt.GraphicsEnvironment;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
@@ -750,18 +751,20 @@
         outerPanel.add(statusBar, BorderLayout.PAGE_END);
 
-        syncDialog = new ExtendedDialog(
-                Main.parent,
-                tr("Correlate images with GPX track"),
-                new String[] {tr("Correlate"), tr("Cancel")},
-                false
-        );
-        syncDialog.setContent(panelTf, false);
-        syncDialog.setButtonIcons(new String[] {"ok", "cancel"});
-        syncDialog.setupDialog();
-        outerPanel.add(syncDialog.getContentPane(), BorderLayout.PAGE_START);
-        syncDialog.setContentPane(outerPanel);
-        syncDialog.pack();
-        syncDialog.addWindowListener(new SyncDialogWindowListener());
-        syncDialog.showDialog();
+        if (!GraphicsEnvironment.isHeadless()) {
+            syncDialog = new ExtendedDialog(
+                    Main.parent,
+                    tr("Correlate images with GPX track"),
+                    new String[] {tr("Correlate"), tr("Cancel")},
+                    false
+            );
+            syncDialog.setContent(panelTf, false);
+            syncDialog.setButtonIcons(new String[] {"ok", "cancel"});
+            syncDialog.setupDialog();
+            outerPanel.add(syncDialog.getContentPane(), BorderLayout.PAGE_START);
+            syncDialog.setContentPane(outerPanel);
+            syncDialog.pack();
+            syncDialog.addWindowListener(new SyncDialogWindowListener());
+            syncDialog.showDialog();
+        }
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 9659)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 9660)
@@ -71,4 +71,8 @@
 public class GeoImageLayer extends Layer implements PropertyChangeListener, JumpToMarkerLayer {
 
+    private static List<Action> menuAdditions = new LinkedList<>();
+
+    private static volatile List<MapMode> supportedMapModes;
+
     List<ImageEntry> data;
     GpxLayer gpxLayer;
@@ -88,10 +92,63 @@
     boolean updateOffscreenBuffer = true;
 
-    /** Loads a set of images, while displaying a dialog that indicates what the plugin is currently doing.
+    private MouseAdapter mouseAdapter;
+    private MapModeChangeListener mapModeListener;
+
+    /**
+     * Constructs a new {@code GeoImageLayer}.
+     * @param data The list of images to display
+     * @param gpxLayer The associated GPX layer
+     */
+    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer) {
+        this(data, gpxLayer, null, false);
+    }
+
+    /**
+     * Constructs a new {@code GeoImageLayer}.
+     * @param data The list of images to display
+     * @param gpxLayer The associated GPX layer
+     * @param name Layer name
+     * @since 6392
+     */
+    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name) {
+        this(data, gpxLayer, name, false);
+    }
+
+    /**
+     * Constructs a new {@code GeoImageLayer}.
+     * @param data The list of images to display
+     * @param gpxLayer The associated GPX layer
+     * @param useThumbs Thumbnail display flag
+     * @since 6392
+     */
+    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, boolean useThumbs) {
+        this(data, gpxLayer, null, useThumbs);
+    }
+
+    /**
+     * Constructs a new {@code GeoImageLayer}.
+     * @param data The list of images to display
+     * @param gpxLayer The associated GPX layer
+     * @param name Layer name
+     * @param useThumbs Thumbnail display flag
+     * @since 6392
+     */
+    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name, boolean useThumbs) {
+        super(name != null ? name : tr("Geotagged Images"));
+        if (data != null) {
+            Collections.sort(data);
+        }
+        this.data = data;
+        this.gpxLayer = gpxLayer;
+        this.useThumbs = useThumbs;
+    }
+
+    /**
+     * Loads a set of images, while displaying a dialog that indicates what the plugin is currently doing.
      * In facts, this object is instantiated with a list of files. These files may be JPEG files or
      * directories. In case of directories, they are scanned to find all the images they contain.
      * Then all the images that have be found are loaded as ImageEntry instances.
      */
-    private static final class Loader extends PleaseWaitRunnable {
+    static final class Loader extends PleaseWaitRunnable {
 
         private boolean canceled;
@@ -102,8 +159,4 @@
         private final GpxLayer gpxLayer;
 
-        protected void rememberError(String message) {
-            this.errorMessages.add(message);
-        }
-
         Loader(Collection<File> selection, GpxLayer gpxLayer) {
             super(tr("Extracting GPS locations from EXIF"));
@@ -111,4 +164,8 @@
             this.gpxLayer = gpxLayer;
             errorMessages = new LinkedHashSet<>();
+        }
+
+        protected void rememberError(String message) {
+            this.errorMessages.add(message);
         }
 
@@ -133,5 +190,5 @@
 
             // read the image files
-            List<ImageEntry> data = new ArrayList<>(files.size());
+            List<ImageEntry> entries = new ArrayList<>(files.size());
 
             for (File f : files) {
@@ -146,7 +203,7 @@
                 ImageEntry e = new ImageEntry(f);
                 e.extractExif();
-                data.add(e);
-            }
-            layer = new GeoImageLayer(data, gpxLayer);
+                entries.add(e);
+            }
+            layer = new GeoImageLayer(entries, gpxLayer);
             files.clear();
         }
@@ -242,55 +299,5 @@
 
     public static void create(Collection<File> files, GpxLayer gpxLayer) {
-        Loader loader = new Loader(files, gpxLayer);
-        Main.worker.execute(loader);
-    }
-
-    /**
-     * Constructs a new {@code GeoImageLayer}.
-     * @param data The list of images to display
-     * @param gpxLayer The associated GPX layer
-     */
-    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer) {
-        this(data, gpxLayer, null, false);
-    }
-
-    /**
-     * Constructs a new {@code GeoImageLayer}.
-     * @param data The list of images to display
-     * @param gpxLayer The associated GPX layer
-     * @param name Layer name
-     * @since 6392
-     */
-    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name) {
-        this(data, gpxLayer, name, false);
-    }
-
-    /**
-     * Constructs a new {@code GeoImageLayer}.
-     * @param data The list of images to display
-     * @param gpxLayer The associated GPX layer
-     * @param useThumbs Thumbnail display flag
-     * @since 6392
-     */
-    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, boolean useThumbs) {
-        this(data, gpxLayer, null, useThumbs);
-    }
-
-    /**
-     * Constructs a new {@code GeoImageLayer}.
-     * @param data The list of images to display
-     * @param gpxLayer The associated GPX layer
-     * @param name Layer name
-     * @param useThumbs Thumbnail display flag
-     * @since 6392
-     */
-    public GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer, final String name, boolean useThumbs) {
-        super(name != null ? name : tr("Geotagged Images"));
-        if (data != null) {
-            Collections.sort(data);
-        }
-        this.data = data;
-        this.gpxLayer = gpxLayer;
-        this.useThumbs = useThumbs;
+        Main.worker.execute(new Loader(files, gpxLayer));
     }
 
@@ -299,6 +306,4 @@
         return ImageProvider.get("dialogs/geoimage");
     }
-
-    private static List<Action> menuAdditions = new LinkedList<>();
 
     public static void registerMenuAddition(Action addition) {
@@ -509,6 +514,6 @@
                 Point p = mv.getPoint(e.getPos());
 
-                int imgWidth = 100;
-                int imgHeight = 100;
+                int imgWidth;
+                int imgHeight;
                 if (useThumbs && e.hasThumbnail()) {
                     Dimension d = scaledDimension(e.getThumbnail());
@@ -570,4 +575,7 @@
     }
 
+    /**
+     * Shows next photo.
+     */
     public void showNextPhoto() {
         if (data != null && !data.isEmpty()) {
@@ -583,4 +591,7 @@
     }
 
+    /**
+     * Shows previous photo.
+     */
     public void showPreviousPhoto() {
         if (data != null && !data.isEmpty()) {
@@ -596,4 +607,7 @@
     }
 
+    /**
+     * Shows first photo.
+     */
     public void showFirstPhoto() {
         if (data != null && !data.isEmpty()) {
@@ -606,4 +620,7 @@
     }
 
+    /**
+     * Shows last photo.
+     */
     public void showLastPhoto() {
         if (data != null && !data.isEmpty()) {
@@ -638,5 +655,5 @@
 
     public void removeCurrentPhotoFromDisk() {
-        ImageEntry toDelete = null;
+        ImageEntry toDelete;
         if (data != null && !data.isEmpty() && currentPhoto >= 0 && currentPhoto < data.size()) {
             toDelete = data.get(currentPhoto);
@@ -684,9 +701,6 @@
 
     public void copyCurrentPhotoPath() {
-        ImageEntry toCopy = null;
         if (data != null && !data.isEmpty() && currentPhoto >= 0 && currentPhoto < data.size()) {
-            toCopy = data.get(currentPhoto);
-            String copyString = toCopy.getFile().toString();
-            Utils.copyToClipboard(copyString);
+            Utils.copyToClipboard(data.get(currentPhoto).getFile().toString());
         }
     }
@@ -759,6 +773,4 @@
     }
 
-    private static volatile List<MapMode> supportedMapModes;
-
     /**
      * Registers a map mode for which the functionality of this layer should be available.
@@ -794,7 +806,4 @@
         return false;
     }
-
-    private MouseAdapter mouseAdapter;
-    private MapModeChangeListener mapModeListener;
 
     @Override
