Bug 552219 - Memory Leak with SWT browser
Summary: Memory Leak with SWT browser
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.7.2   Edit
Hardware: PC Windows 10
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-10-18 10:13 EDT by pinar cana CLA
Modified: 2021-02-08 09:37 EST (History)
2 users (show)

See Also:


Attachments
Jar file for test tool (4.58 MB, application/octet-stream)
2019-10-18 10:13 EDT, pinar cana CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description pinar cana CLA 2019-10-18 10:13:44 EDT
Created attachment 280323 [details]
Jar file for test tool

In our application we are opening many pdf documents daily within internet explorer using SWT Browser. After opening 100 documents our application is not responding anymore. 

Below you can find the source code for atest tool to reproduce the memory leak after opening several(~1000) documents. 

We also tested the same without pdf documents to eliminate any issue with pdf viewer. If we just open "maps.google.com", we are having the same problem, the memory grows very fast and the application crashes.


java -jar browserTest.jar "http://www.orimi.com/pdf-test.pdf" 


package com.db;

import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

public class BrowserTest {
	int index;
	Text location;
	final String ABOUT_BLANK = "";
	Browser browser;
	static Display display;
	static String browserUrl;

	public BrowserTest(final Composite parent) {
		display = parent.getDisplay();
		FormLayout layout = new FormLayout();
		parent.setLayout(layout);
		ToolBar toolbar = new ToolBar(parent, 0);

		this.location = new Text(parent, 2048);

		final Canvas canvas = new Canvas(parent, 262144);
		final Label status = new Label(parent, 0);

		FormData data = new FormData();
		data.top = new FormAttachment(0, 5);
		toolbar.setLayoutData(data);

		data = new FormData();
		data.width = 24;
		data.height = 24;
		data.top = new FormAttachment(0, 5);
		data.right = new FormAttachment(100, -5);
		canvas.setLayoutData(data);

		data = new FormData();
		data.top = new FormAttachment(toolbar, 0, 128);
		data.left = new FormAttachment(toolbar, 5, 131072);
		data.right = new FormAttachment(canvas, -5, -1);
		this.location.setLayoutData(data);

		data = new FormData();
		data.left = new FormAttachment(0, 5);
		data.bottom = new FormAttachment(100, -5);
		status.setLayoutData(data);

		data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.bottom = new FormAttachment(100, -5);

		final ToolItem createToolItem = new ToolItem(toolbar, 8);
		createToolItem.setText("create");

		Listener listener = new Listener() {
			public void handleEvent(Event event) {
				ToolItem item = (ToolItem) event.widget;
				System.out.println("Create Browser");
				if ((item == createToolItem) && (BrowserTest.this.browser == null)) {
					BrowserTest.this.createBrowser(parent, canvas, status);
				}

			}
		};
		createToolItem.addListener(13, listener);

		final ToolItem disposeToolItem = new ToolItem(toolbar, 8);
		disposeToolItem.setText("dispose");

		listener = new Listener() {
			public void handleEvent(Event event) {
				System.out.println("Dispose Browser");
				ToolItem item = (ToolItem) event.widget;
				if (item == disposeToolItem) {
					BrowserTest.this.disposeBrowser();
				}

			}

		};
		disposeToolItem.addListener(13, listener);

		ToolItem autoToolItem = new ToolItem(toolbar, 8);
		autoToolItem.setText("Start");

		final Thread thread = getTask2(createToolItem, disposeToolItem, this.location);

		listener = new Listener() {
			public void handleEvent(Event event) {
				thread.start();
			}

		};
		autoToolItem.addListener(13, listener);

		ToolItem autoToolItem2 = new ToolItem(toolbar, 8);
		autoToolItem2.setText("Stop");

		listener = new Listener() {
			public void handleEvent(Event event) {
				thread.stop();
			}

		};
		autoToolItem2.addListener(13, listener);

		this.location.addListener(14, new Listener() {
			public void handleEvent(Event e) {
				if (BrowserTest.this.browser != null) {
					BrowserTest.this.browser.setUrl(BrowserTest.this.location.getText());
				}
			}
		});
	}

	public static Thread getTask2(ToolItem create, final ToolItem dispose, final Text location) {
		return new Thread() {
			public void run() {
				for (int i = 0; i < 10000; i++) {
					final int x = i;

					BrowserTest.display.asyncExec(new Runnable() {
						public void run() {
							System.out.println("Iteration: " + x);
							create.notifyListeners(13, null);

							location.setText(BrowserTest.browserUrl);
							location.notifyListeners(14, null);
						}
					});

					try {
						Thread.sleep(3000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					BrowserTest.display.asyncExec(new Runnable() {
						public void run() {
							dispose.notifyListeners(13, null);
						}
					});
					try {
						Thread.sleep(500L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
	}

	private void createBrowser(Composite parent, Canvas canvas, Label status) {
		FormData data = new FormData();
		data.left = new FormAttachment(0, 0);
		data.right = new FormAttachment(100, 0);
		data.top = new FormAttachment(canvas, 5, -1);
		data.bottom = new FormAttachment(status, -5, -1);
		this.browser = new Browser(parent,0);
		this.browser.setLayoutData(data);
		((Shell) parent).layout();

		
		this.browser.addLocationListener(new LocationListener() {
			public void changed(LocationEvent event) {
				if (event.top) {
					BrowserTest.this.location.setText(event.location);
				}
			}

			public void changing(LocationEvent event) {
			}
		});
	}

	private void disposeBrowser() {
		if (this.browser != null) {			
			this.browser.dispose();
			this.browser = null;
		}
	}

	public static void main(String[] args) {
		browserUrl = args[0];
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		new BrowserTest(shell);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}
Comment 1 Guillaume Genoud CLA 2021-02-08 09:37:05 EST
We are experiencing the same problems with our application.

Did anyone manage to solve this memory leak or to find a workaround ?

Thanks for the reply.

Guillaume