Created
July 24, 2016 16:50
-
-
Save hollingsworthd/07348e7297059e47adb8d31c2902d86a to your computer and use it in GitHub Desktop.
Memory Leak in JRE WebView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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