diff -r 66e9f68ec095 modules/web/src/main/java/com/sun/webkit/Disposer.java
--- a/modules/web/src/main/java/com/sun/webkit/Disposer.java	Wed Nov 30 20:38:50 2016 +0100
+++ b/modules/web/src/main/java/com/sun/webkit/Disposer.java	Thu Dec 01 23:40:27 2016 +0100
@@ -88,6 +88,11 @@
         disposerInstance.add(target, rec);
     }
 
+    public static void flush() {
+        disposerInstance.cleanUp(true);
+        DisposerRunnable.getInstance().waitFinished();
+    }
+
     /**
      * Performs the actual registration of the target object to be disposed.
      * @param target Object to be registered
@@ -98,10 +103,23 @@
         records.add(new WeakDisposerRecord(target, rec));
     }
 
+    @Override
     public void run() {
+        cleanUp(false);
+    }
+
+    private void cleanUp(boolean poll) {
         while (true) {
             try {
-                WeakDisposerRecord obj = (WeakDisposerRecord) queue.remove();
+                WeakDisposerRecord obj;
+                if (poll) {
+                    obj = (WeakDisposerRecord) queue.poll();
+                    if (obj == null) {
+                        return;
+                    }
+                } else {
+                    obj = (WeakDisposerRecord) queue.remove();
+                }
                 obj.clear();
                 DisposerRunnable.getInstance().enqueue(obj);
             } catch (Exception e) {
@@ -144,6 +162,7 @@
                     obj = disposerQueue.poll();
                     if (obj == null) {
                         isRunning = false;
+                        disposerLock.notifyAll();
                         break;
                     }
                 }
@@ -154,6 +173,18 @@
                 }
             }
         }
+
+        private void waitFinished() {
+            synchronized (disposerLock) {
+                while (isRunning) {
+                    try {
+                        disposerLock.wait();
+                    } catch (InterruptedException ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            }
+        }
     }
 
     public static class WeakDisposerRecord
diff -r 66e9f68ec095 modules/web/src/test/java/javafx/scene/web/LeakTest.java
--- a/modules/web/src/test/java/javafx/scene/web/LeakTest.java	Wed Nov 30 20:38:50 2016 +0100
+++ b/modules/web/src/test/java/javafx/scene/web/LeakTest.java	Thu Dec 01 23:40:27 2016 +0100
@@ -25,8 +25,10 @@
 
 package javafx.scene.web;
 
+import com.sun.webkit.Disposer;
 import com.sun.webkit.WebPage;
 import java.io.File;
+import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
@@ -36,6 +38,9 @@
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.util.Duration;
+import netscape.javascript.JSObject;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
 import org.junit.Ignore;
 import org.junit.Test;
 import static org.junit.Assert.assertNull;
@@ -44,6 +49,79 @@
 
 public class LeakTest extends TestBase {
 
+    @Test
+    public void multipleJSObjectsForASinglePeer() throws Exception {
+        testMultipleJSObjects(true);
+    }
+
+    @Test
+    public void multipleJSObjectsForMultiplePeers() throws Exception {
+        testMultipleJSObjects(false);
+    }
+
+    private void testMultipleJSObjects(boolean singlePeer) throws Exception {
+        Reference<?>[] willGC = new Reference[3];
+        JSObject[] toCheck = new JSObject[1];
+        int expectedValue = submit(() -> {
+            Object rawFn = getEngine().executeScript(""
+                    + "(function(add) {\n"
+                    + "  if (" + singlePeer + " && window.obj) {\n"
+                    + "     window.obj.count += add;\n"
+                    + "  } else {\n"
+                    + "     window.obj = {};\n"
+                    + "     window.obj.count = add;\n"
+                    + "  }\n"
+                    + "  return window.obj;\n"
+                    + "})"
+            );
+            assertTrue(rawFn instanceof JSObject);
+            JSObject fn = (JSObject)rawFn;
+
+            JSObject first = (JSObject) fn.call("call", null, 1);
+            JSObject second = (JSObject) fn.call("call", null, 1);
+            JSObject third = (JSObject) fn.call("call", null, 1);
+
+            getEngine().executeScript("window.obj = null");
+
+            if (singlePeer) {
+                assertEquals("Values of the same JS obj incremented", first.getMember("count"), 3);
+                assertEquals("Values of the same JS obj incremented", second.getMember("count"), 3);
+                assertEquals("Values of the same JS obj incremented", third.getMember("count"), 3);
+            } else {
+                assertEquals("Values of the different JS obj used", first.getMember("count"), 1);
+                assertEquals("Values of the different JS obj used", second.getMember("count"), 1);
+                assertEquals("Values of the different JS obj used", third.getMember("count"), 1);
+            }
+
+            assertNotSame(first, second);
+            assertNotSame(third, second);
+
+            willGC[0] = new WeakReference<>(first);
+            willGC[1] = new WeakReference<>(second);
+            toCheck[0] = third;
+
+            return (int)third.getMember("count");
+        });
+
+        assertGC("First JSObject can disappear", willGC[0]);
+        assertGC("Second JSObject can disappear", willGC[1]);
+
+
+        for (int i = 5; i < 20; i++) {
+            Disposer.flush();
+            messWithJavaScriptMemory((int) Math.pow(2, i));
+            
+            submit(() -> {
+                JSObject third = toCheck[0];
+                assertEquals("Value of third JS object is still same", third.getMember("count"), expectedValue);
+                willGC[2] = new WeakReference<>(third);
+            });
+        }
+        
+        toCheck[0] = null;
+        assertGC("Third JSObject can disappear", willGC[2]);
+    }
+
     @Ignore // RT-26710: javafx.scene.web.LeakTest hangs
     @Test public void testOleg() throws InterruptedException{
         final String URL = new File("src/test/resources/html/guimark2-vector.html").toURI().toASCIIString();
@@ -102,4 +180,37 @@
             Thread.sleep(100);
         }
     }
+
+    private static void assertGC(String msg, Reference<?> ref) throws InterruptedException {
+        for (int i = 0; i < 100; i++) {
+            if (isGone(ref)) {
+                return;
+            }
+
+            try {
+                System.gc();
+                System.runFinalization();
+            } catch (Error err) {
+                err.printStackTrace();
+            }
+        }
+        throw new InterruptedException(msg);
+    }
+
+    private static boolean isGone(Reference<?> ref) {
+        return ref.get() == null;
+    }
+
+    private void messWithJavaScriptMemory(int allocate) {
+        String gc = "var max = " + allocate + ";\n"
+            + "var arr = [];\n"
+            + "for (var i = 0; i < max; i++) {\n"
+            + "  arr.push(i);\n"
+            + "}\n"
+            + "arr.length";
+        submit(() -> {
+            Object res = getEngine().executeScript(gc);
+            assertEquals("Expected size created", allocate, res);
+        });
+    }
 }
