I would like to see is there a way to resolve this issue: either through coding or configuration changes. Any advice and suggestions will be greatly appreciated.
I have encountered the memory leak/accumulation issue using a _javascript_ WebSocket client communicates with a local application Jetty WebSocket server (using Jetty's WebSocket JSR356 implementation). I have tried both Jetty 9.3.3.v20150827 and 9.3.5.v20151012 and the memory leak issue can both be observed. Java version is "1.8.0_60".
What I want to achieve is sending files (one at a time as instructed by the user) from the Browser _javascript_ WebSocket client to the Jetty WebSocket server for processing.
Two memory leak/accumulation issues are observed (using Eclipse Memory Analyzer) at the Jetty WebSocket server side:
Below are excerpted (with simplification) from both client and server sides:
================================================================================
_javascript_ WebSocket client side:
=============================================
function sendFile(file) {
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader._onload_ = function() {
// this websocket object has been setup somewhere else in advance with binaryType = "blob"
websocket.send(reader.result);
}
}
Jetty WebSocket server side:
======================================
WSServer.java
-------------
package mytestapp;
import javax.websocket.server.ServerContainer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
public class WSServer {
public static void main(String[] args) {
Server server = new Server();
// Connector
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
ServletContextHandler ctx = new ServletContextHandler(ServletContextHandler.SESSIONS);
ctx.setContextPath("/");
server.setHandler(ctx);
server.addConnector(connector);
try {
// Initialize javax.websocket layer
ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(ctx);
// Add WebSocket endpoint to javax.websocket layer
wscontainer.addEndpoint(WSEndpoint.class);
wscontainer.setDefaultMaxSessionIdleTimeout(0);
wscontainer.setDefaultMaxTextMessageBufferSize(Integer.MAX_VALUE);
wscontainer.setDefaultMaxBinaryMessageBufferSize(Integer.MAX_VALUE);
server.start();
server.join();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
WSEndpoint.java
---------------
package mytestapp;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/")
public class WSEndpoint {
@OnOpen
public void onOpen(Session session) throws IOException {
System.out.println("onOpen");
}
@OnMessage
public void onText(String message, Session session) {
System.out.println("onText");
}
@OnMessage
public void onBinary(ByteBuffer bb, Session session) {
System.out.println("Got binary message, do nothing to make sure there is no reference to ByteBuffer and Session");
}
@OnError
public void onError(Throwable t) {
System.out.println("Received error: " + t.getMessage());
}
@OnClose
public void onClose(Session session) {
System.out.println("onClose");
}
}
================================================================================
Thanks,
Mike