diff --git a/apps/experiments/ConferenceScheduleApp/src/main/java/com/javafx/experiments/scheduleapp/pages/SpeakersPage.java b/apps/experiments/ConferenceScheduleApp/src/main/java/com/javafx/experiments/scheduleapp/pages/SpeakersPage.java
--- a/apps/experiments/ConferenceScheduleApp/src/main/java/com/javafx/experiments/scheduleapp/pages/SpeakersPage.java
+++ b/apps/experiments/ConferenceScheduleApp/src/main/java/com/javafx/experiments/scheduleapp/pages/SpeakersPage.java
@@ -140,9 +140,7 @@
         // hardware layer support. This code will just move the keyboard out of the way.
         searchBox.focusedProperty().addListener(new InvalidationListener() {
             @Override public void invalidated(Observable observable) {
-                Iterator<Window> itr = Window.impl_getWindows();
-                while (itr.hasNext()) {
-                    Window win = itr.next();
+                for (Window win : Window.getWindows()) {
                     Object obj = win.getScene().getRoot().lookup(".fxvk");
                     if (obj instanceof FXVK) {
                         FXVK keyboard = (FXVK) obj;
diff --git a/apps/toys/Hello/src/main/java/hello/HelloPopup.java b/apps/toys/Hello/src/main/java/hello/HelloPopup.java
--- a/apps/toys/Hello/src/main/java/hello/HelloPopup.java
+++ b/apps/toys/Hello/src/main/java/hello/HelloPopup.java
@@ -128,11 +128,10 @@
             }
 
             nextPopup.show(popupParent, popupX, popupY);
-            
-            Iterator<Window> windows = Window.impl_getWindows();
-            while (windows.hasNext()) {
-                System.out.println("W: " + windows.next().getClass().getName());
-            }
+
+            Window.getWindows().stream().forEach(window -> {
+                System.out.println("W: " + window.getClass().getName());
+            });
         }
     }
 
diff --git a/modules/graphics/src/main/java/com/sun/javafx/tk/Toolkit.java b/modules/graphics/src/main/java/com/sun/javafx/tk/Toolkit.java
--- a/modules/graphics/src/main/java/com/sun/javafx/tk/Toolkit.java
+++ b/modules/graphics/src/main/java/com/sun/javafx/tk/Toolkit.java
@@ -855,14 +855,12 @@
      */
     public void pauseScenes() {
         pauseScenesLatch = new CountDownLatch(1);
-        Iterator<Window> i = Window.impl_getWindows();
-        while (i.hasNext()) {
-            final Window w = i.next();
-            final Scene scene = w.getScene();
+        Window.getWindows().stream().forEach(window -> {
+            final Scene scene = window.getScene();
             if (scene != null) {
                 this.removeSceneTkPulseListener(scene.impl_getScenePulseListener());
             }
-        }
+        });
         this.getMasterTimer().pause();
         SceneHelper.setPaused(true);
     }
@@ -874,14 +872,12 @@
     public void resumeScenes() {
         SceneHelper.setPaused(false);
         this.getMasterTimer().resume();
-        Iterator<Window> i = Window.impl_getWindows();
-        while (i.hasNext()) {
-            final Window w = i.next();
-            final Scene scene = w.getScene();
+        Window.getWindows().stream().forEach(window -> {
+            final Scene scene = window.getScene();
             if (scene != null) {
                 this.addSceneTkPulseListener(scene.impl_getScenePulseListener());
             }
-        }
+        });
         pauseScenesLatch.countDown();
         pauseScenesLatch = null;
     }
diff --git a/modules/graphics/src/main/java/javafx/stage/Window.java b/modules/graphics/src/main/java/javafx/stage/Window.java
--- a/modules/graphics/src/main/java/javafx/stage/Window.java
+++ b/modules/graphics/src/main/java/javafx/stage/Window.java
@@ -28,9 +28,12 @@
 import java.security.AllPermission;
 import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 
+import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.DoublePropertyBase;
 import javafx.beans.property.ObjectProperty;
@@ -43,6 +46,7 @@
 import javafx.beans.property.ReadOnlyDoubleWrapper;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
 import javafx.collections.ObservableMap;
 import javafx.event.Event;
 import javafx.event.EventDispatchChain;
@@ -77,9 +81,10 @@
 public class Window implements EventTarget {
 
     /**
-     * A list of all the currently existing windows. This is only used by SQE for testing.
+     * A list of all the currently _showing_ windows. This is publicly accessible via the unmodifiableWindows wrapper.
      */
-    private static WeakReferenceQueue<Window>windowQueue = new WeakReferenceQueue<Window>();
+    private static ObservableList<Window> windows = FXCollections.observableArrayList();
+    private static ObservableList<Window> unmodifiableWindows = FXCollections.unmodifiableObservableList(windows);
 
     static {
         WindowHelper.setWindowAccessor(
@@ -134,20 +139,20 @@
     }
 
     /**
-     * Return all Windows
+     * Returns a list containing a reference to the currently showing JavaFX windows. The list is unmodifiable -
+     * attempting to modify this list will result in an {@link UnsupportedOperationException} being thrown at runtime.
      *
-     * @return Iterator of all Windows
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
+     * @return A list containing all windows that are currently showing.
+     * @since 9
      */
-    @Deprecated
-    public static Iterator<Window> impl_getWindows() {
+    @ReturnsUnmodifiableCollection
+    public static ObservableList<Window> getWindows() {
         final SecurityManager securityManager = System.getSecurityManager();
         if (securityManager != null) {
             securityManager.checkPermission(new AllPermission());
         }
 
-        return (Iterator<Window>) windowQueue.iterator();
+        return unmodifiableWindows;
     }
 
     final AccessControlContext acc = AccessController.getContext();
@@ -824,9 +829,9 @@
             impl_visibleChanging(newVisible);
             if (newVisible) {
                 hasBeenVisible = true;
-                windowQueue.add(Window.this);
+                windows.add(Window.this);
             } else {
-                windowQueue.remove(Window.this);
+                windows.remove(Window.this);
             }
             Toolkit tk = Toolkit.getToolkit();
             if (impl_peer != null) {
diff --git a/modules/graphics/src/test/java/test/javafx/stage/WindowTest.java b/modules/graphics/src/test/java/test/javafx/stage/WindowTest.java
--- a/modules/graphics/src/test/java/test/javafx/stage/WindowTest.java
+++ b/modules/graphics/src/test/java/test/javafx/stage/WindowTest.java
@@ -28,9 +28,13 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.assertNotNull;
+
+import javafx.beans.InvalidationListener;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.SimpleDoubleProperty;
 
+import javafx.collections.ObservableList;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -41,6 +45,8 @@
 import javafx.stage.Stage;
 import javafx.stage.Window;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 public final class WindowTest {
     private StubToolkit toolkit;
     private Stage testWindow;
@@ -51,6 +57,12 @@
         testWindow = new Stage();
     }
 
+    @After
+    public void afterTest() {
+        testWindow.hide();
+        testWindow = null;
+    }
+
     @Test
     public void testOpacityBind() {
         final DoubleProperty variable = new SimpleDoubleProperty(0.5);
@@ -97,4 +109,61 @@
         assertTrue(unkPeer instanceof StubStage);
         return (StubStage) unkPeer;
     }
+
+    @Test public void testGetWindowsIsObservable() {
+        AtomicInteger windowCount = new AtomicInteger(0);
+        ObservableList<Window> windows = Window.getWindows();
+
+        InvalidationListener listener = o -> windowCount.set(windows.size());
+        windows.addListener(listener);
+
+        assertEquals(0, windowCount.get());
+
+        testWindow.show();
+        assertEquals(1, windowCount.get());
+
+        Stage anotherTestWindow = new Stage();
+        anotherTestWindow.show();
+        assertEquals(2, windowCount.get());
+
+        testWindow.hide();
+        assertEquals(1, windowCount.get());
+
+        anotherTestWindow.hide();
+        assertEquals(0, windowCount.get());
+
+        windows.removeListener(listener);
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetWindowsIsUnmodifiable_add() {
+        Stage anotherTestWindow = new Stage();
+        Window.getWindows().add(anotherTestWindow);
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetWindowsIsUnmodifiable_removeShowingWindow() {
+        testWindow.show();
+        Window.getWindows().remove(testWindow);
+    }
+
+    // There is no UOE here because the window being removed is not in the list of windows,
+    // so no modification of the windows list occurs.
+    @Test public void testGetWindowsIsUnmodifiable_removeNonShowingWindow_emptyList() {
+        Stage anotherTestWindow = new Stage();
+        Window.getWindows().remove(anotherTestWindow);
+    }
+
+    // There is no UOE here because the window being removed is not in the list of windows,
+    // so no modification of the windows list occurs.
+    @Test public void testGetWindowsIsUnmodifiable_removeNonShowingWindow_nonEmptyList() {
+        testWindow.show();
+        assertEquals(1, Window.getWindows().size());
+
+        Stage anotherTestWindow = new Stage();
+        assertEquals(1, Window.getWindows().size());
+
+        Window.getWindows().remove(anotherTestWindow);
+        assertEquals(1, Window.getWindows().size());
+    }
 }
diff --git a/modules/jmx/src/main/java/com/oracle/javafx/jmx/SGMXBeanImpl.java b/modules/jmx/src/main/java/com/oracle/javafx/jmx/SGMXBeanImpl.java
--- a/modules/jmx/src/main/java/com/oracle/javafx/jmx/SGMXBeanImpl.java
+++ b/modules/jmx/src/main/java/com/oracle/javafx/jmx/SGMXBeanImpl.java
@@ -362,12 +362,10 @@
 
     private void importWindows() {
         int windowCount = 0;
-        final Iterator<Window> it = Window.impl_getWindows();
+        final List<Window> windows = Window.getWindows();
 
         jwindows = JSONDocument.createArray();
-        while (it.hasNext()) {
-            final Window window = it.next();
-
+        for (Window window : windows) {
             windowMap.put(windowCount, window);
 
             final JSONDocument jwindow = JSONDocument.createObject();
diff --git a/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_sceneGraph_Test.java b/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_sceneGraph_Test.java
--- a/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_sceneGraph_Test.java
+++ b/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_sceneGraph_Test.java
@@ -43,6 +43,7 @@
 
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 public class SGMXBean_sceneGraph_Test {
@@ -74,12 +75,10 @@
         stage2.setScene(scene2);
         stage2.show();
 
-        final Iterator<Window> it = Window.impl_getWindows();
+        final List<Window> windows = Window.getWindows();
         nodesCount = 0;
-        while (it.hasNext()) {
-            final Window w = it.next();
+        for (Window w : windows) {
             nodesCount += countNodes(w.getScene().getRoot());
-
         }
     }
 
diff --git a/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_windows_Test.java b/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_windows_Test.java
--- a/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_windows_Test.java
+++ b/modules/jmx/src/test/java/com/oracle/javafx/jmx/SGMXBean_windows_Test.java
@@ -42,6 +42,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.List;
 
 public class SGMXBean_windows_Test {
 
@@ -66,12 +67,8 @@
         stage2.setScene(scene2);
         stage2.show();
 
-        final Iterator<Window> it = Window.impl_getWindows();
-        windowsCount = 0;
-        while (it.hasNext()) {
-            windowsCount++;
-            it.next();
-        }
+        final List<Window> windows = Window.getWindows();
+        windowsCount = windows.size();
     }
 
     private static JSONDocument getJSONDocument(String source) {
diff --git a/tools/ios/Maven/NetBeansMobileCenter/src/main/java/com/sun/javafx/stage/WindowManager.java b/tools/ios/Maven/NetBeansMobileCenter/src/main/java/com/sun/javafx/stage/WindowManager.java
--- a/tools/ios/Maven/NetBeansMobileCenter/src/main/java/com/sun/javafx/stage/WindowManager.java
+++ b/tools/ios/Maven/NetBeansMobileCenter/src/main/java/com/sun/javafx/stage/WindowManager.java
@@ -38,9 +38,7 @@
     public static void closeApplicationWindows(
             final ClassLoader appClassLoader) {
         final List<Window> selectedWindows = new ArrayList<Window>();
-        final Iterator<Window> allWindows = Window.impl_getWindows();
-        while (allWindows.hasNext()) {
-            final Window window = allWindows.next();
+        for (Window window : Window.getWindows()) {
             if (matches(window, appClassLoader)) {
                 selectedWindows.add(window);
             }