The MessageApplet.java revised: import java.applet.Applet; import java.util.Stack; import java.util.concurrent.LinkedBlockingQueue; import netscape.javascript.JSObject; public class MessageApplet extends Applet { private MessagePool pool; class MessageHandle { int id; MessagePool pool; JSObject object; MessageHandle (int id , Object object , MessagePool pool) { this.id = id; this.pool = pool; if (object instanceof JSObject) this.object = (JSObject) object; } public int getId () { return id; } public JSObject getMessageObject () { return pool.getMessageObject(id , object); } public void free () { if (id != -1) { pool.freeMessage (id); id = -1; } } protected void finalize() throws Throwable { free (); super.finalize(); } } class MessagePool { private JSObject messagePool; private int idCounter; private Stack freeHandles; MessagePool (Applet applet) { freeHandles = new Stack (); final JSObject window = JSObject.getWindow(applet); final String tmpName = "_MessagePool" + System.identityHashCode(this); window.eval("var "+ tmpName +" = {}"); messagePool = (JSObject)window.getMember(tmpName); } public MessageHandle createMessage (Object o) { int id; synchronized (freeHandles) { if (freeHandles.isEmpty()) { id = idCounter++; } else { id = freeHandles.pop(); } } messagePool.setMember("Message" + id , o); return new MessageHandle (id , o , this); } public JSObject getMessageObject (int id , JSObject object) { Object obj = messagePool.getMember("Message" + id); // this will not work in IE6 if (obj instanceof JSObject) return (JSObject) obj; return object; } public void freeMessage (int id) { messagePool.setMember("Message" + id , null); synchronized (freeHandles) { freeHandles.push(id); } } } class MessageWorker implements Runnable { LinkedBlockingQueue queue; MessageWorker () { queue = new LinkedBlockingQueue (); } void insertMessage (MessageHandle message) { try { queue.put(message); } catch (InterruptedException e) { // TODO } } public void run() { for (;;) { try { MessageHandle message = queue.take(); dispatchMessage (message); } catch (InterruptedException e) { // TODO } } } public void dispatchMessage (MessageHandle messageHandle) { JSObject message = messageHandle.getMessageObject(); System.out.println (message); Object [] noArgs = new Object [0]; Object [] oneArg = new Object [1]; int parameterCount = toInteger (message.call("getParametersLength", noArgs)); int localCount = toInteger (message.call("getLocalParametersLength", noArgs)); // skip local parameters for (int i = localCount; i < parameterCount; i++) { oneArg[0] = new Integer(i); String param = (String) message.call("getParameter", oneArg); // add something to parameter oneArg[0] = new String (param + "-Message id "+ messageHandle.getId() + "-Message worker-"+hashCode()); message.call("addResponse" , oneArg); } message.call("callback", noArgs); messageHandle.free(); } } static MessageWorker worker = null; static Object lock = new Object (); public void insertMessage (Object message) { MessageHandle handle = pool.createMessage(message); worker.insertMessage(handle); } public void init() { synchronized (lock) // maybe two applets starting at same time ? Probaly this should be an integer to count references and destroy when all others exits. { if (pool == null) pool = new MessagePool (this); if (worker == null) { worker = new MessageWorker (); Thread thread = new Thread (worker); thread.start(); } } super.init(); } public static int toInteger (Object obj) { if (obj == null) return 0; if (obj instanceof Integer) // IE6 and Chrome { return ((Integer) obj).intValue(); } else if (obj instanceof Double) // FF 2.0 { return ((Double) obj).intValue(); } else if (obj instanceof String) // dont know { return Integer.parseInt((String) obj); } return 0; } public void destroy () { super.destroy(); } } HTML sligthly revised (without referencing to a local array and the done method):

Test it