Skip to content

Instantly share code, notes, and snippets.

@hollingsworthd
Created July 24, 2016 16:50
Show Gist options
  • Save hollingsworthd/07348e7297059e47adb8d31c2902d86a to your computer and use it in GitHub Desktop.
Save hollingsworthd/07348e7297059e47adb8d31c2902d86a to your computer and use it in GitHub Desktop.
Memory Leak in JRE WebView
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Base64;
import com.sun.javafx.webkit.Accessor;
import com.sun.webkit.LoadListenerClient;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewMemoryLeak extends Application {
private static final int PORT = 9000;
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
WebView view = new WebView();
WebEngine engine = view.getEngine();
engine.load("http://127.0.0.1:" + PORT);
root.getChildren().add(view);
Accessor.getPageFor(engine).addLoadListenerClient(new LoadListenerClient() {
@Override
public void dispatchResourceLoadEvent(long frame, int state, String url, String contentType, double progress, int errorCode) {}
@Override
public void dispatchLoadEvent(long frame, int state, String url, String contentType, double progress, int errorCode) {
Accessor.getPageFor(engine).getOwnerElement(frame); //leaks memory
Accessor.getPageFor(engine).getDocument(frame); //also leaks memory
if (state == LoadListenerClient.PAGE_FINISHED) {
engine.load("http://127.0.0.1:" + PORT);
}
}
});
Scene scene = new Scene(root, 100, 100);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) throws IOException, InterruptedException {
launchServer(PORT);
Application.launch(args);
}
private static final byte[] indexBody;
private static final byte[] indexHeaders;
private static final byte[] imageBody;
private static final byte[] imageHeaders;
static {
indexBody = "<html><head></head><body><img src=\"/image.png\"></body></html>".getBytes();
indexHeaders = headers(indexBody, "text/html");
imageBody = Base64.getDecoder().decode(
"iVBORw0KGgoAAAANSUhEUgAAAyAAAAMgCAIAAABUEpE/AAAHW0lEQVR42u3BAQEAAACCIP+vbkhAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwaUNMAAWZG6bQAAAAASUVORK5CYII=");
imageHeaders = headers(imageBody, "image/png");
}
private static byte[] headers(byte[] body, String contentType) {
byte[] headersTmp = null;
headersTmp = new String("HTTP/1.1 200 OK\n"
+ "Content-Type: " + contentType + "\n"
+ "Content-Length: " + body.length + "\n"
+ "Connection: close\n\n").getBytes();
return headersTmp;
}
public static void launchServer(int port) {
new Thread(new Runnable() {
@Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(port, Integer.MAX_VALUE, InetAddress.getByName("127.0.0.1"))) {
while (true) {
try (Socket socket = serverSocket.accept();
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
for (String line; (line = reader.readLine()) != null;) {
if (line.startsWith("GET / ")) {
output.write(indexHeaders, 0, indexHeaders.length);
output.write(indexBody, 0, indexBody.length);
} else if (line.startsWith("GET /image.png")) {
output.write(imageHeaders, 0, imageHeaders.length);
output.write(imageBody, 0, imageBody.length);
}
}
}
}
} catch (Throwable t) {}
}
}).start();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment