beta_java_18_3 branch merged  to master
diff --git a/org.eclipse.jdt.debug.jdi.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.debug.jdi.tests/.settings/org.eclipse.jdt.core.prefs
index 17c4a10..2fd230a 100644
--- a/org.eclipse.jdt.debug.jdi.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jdt.debug.jdi.tests/.settings/org.eclipse.jdt.core.prefs
@@ -220,10 +220,10 @@
 org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert

diff --git a/org.eclipse.jdt.debug.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.debug.tests/.settings/org.eclipse.jdt.core.prefs
index 79bbe1b..8bbf89e 100644
--- a/org.eclipse.jdt.debug.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jdt.debug.tests/.settings/org.eclipse.jdt.core.prefs
@@ -220,10 +220,10 @@
 org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert

diff --git a/org.eclipse.jdt.debug.tests/JDT Debug Test Suite.launch b/org.eclipse.jdt.debug.tests/JDT Debug Test Suite.launch
index 09ee572..fd7c8f7 100644
--- a/org.eclipse.jdt.debug.tests/JDT Debug Test Suite.launch
+++ b/org.eclipse.jdt.debug.tests/JDT Debug Test Suite.launch
@@ -33,7 +33,7 @@
 <stringAttribute key="pde.version" value="3.3"/>

 <stringAttribute key="product" value="org.eclipse.sdk.ide"/>

 <booleanAttribute key="run_in_ui_thread" value="true"/>

-<stringAttribute key="selected_target_plugins" value="org.eclipse.team.cvs.core@default:default,com.jcraft.jsch@default:default,org.eclipse.core.commands@default:default,org.eclipse.ltk.ui.refactoring@default:default,org.apache.jasper@default:default,org.eclipse.equinox.frameworkadmin.equinox@default:default,org.eclipse.core.databinding.beans@default:default,org.eclipse.jsch.core@default:default,org.eclipse.equinox.p2.updatechecker@default:default,org.eclipse.equinox.p2.ui.sdk@default:default,org.eclipse.help@default:default,org.eclipse.ui.net@default:default,org.eclipse.ui.intro.universal@default:default,org.eclipse.help.base@default:default,org.eclipse.equinox.p2.garbagecollector@default:default,org.mortbay.jetty.util@default:default,org.eclipse.equinox.security.ui@default:default,org.eclipse.equinox.p2.metadata.generator@default:default,org.eclipse.core.filesystem.linux.x86@default:false,org.sat4j.pb@default:default,org.eclipse.platform@default:default,org.eclipse.equinox.jsp.jasper@default:default,org.eclipse.pde.ds.ui@default:default,org.apache.commons.logging@default:default,org.eclipse.equinox.common@default:default,org.eclipse.pde@default:default,org.eclipse.core.resources.compatibility@default:false,org.eclipse.core.net@default:default,org.eclipse.core.filebuffers@default:default,org.eclipse.equinox.p2.directorywatcher@default:default,org.eclipse.equinox.security@default:default,org.eclipse.core.filesystem@default:default,org.eclipse.rcp@default:default,org.eclipse.ecf.provider.filetransfer.httpclient.ssl@default:false,org.eclipse.update.scheduler@default:default,org.eclipse.equinox.p2.console@default:default,org.eclipse.sdk@default:default,org.eclipse.swt@default:default,org.eclipse.ui.views@default:default,org.apache.commons.codec@default:default,org.eclipse.core.databinding@default:default,org.eclipse.ui.workbench.texteditor@default:default,org.eclipse.equinox.jsp.jasper.registry@default:default,org.eclipse.compare.core@default:default,org.eclipse.update.core@default:default,org.eclipse.equinox.p2.touchpoint.eclipse@default:default,org.eclipse.core.expressions@default:default,org.eclipse.equinox.p2.director@default:default,org.eclipse.ui.workbench@default:default,org.eclipse.jdt.junit4.runtime@default:default,org.eclipse.jdt.junit.runtime@default:default,org.eclipse.ui.forms@default:default,org.eclipse.equinox.p2.publisher@default:default,org.eclipse.ui.navigator.resources@default:default,org.eclipse.osgi.services@default:default,org.eclipse.help.appserver@default:default,org.eclipse.update.ui@default:default,org.mortbay.jetty.server@default:default,org.junit@default:default,org.eclipse.equinox.p2.director.app@default:default,org.eclipse.equinox.p2.ui.sdk.scheduler@default:default,org.eclipse.cvs@default:default,org.eclipse.ecf.provider.filetransfer@default:default,org.eclipse.jface.text@default:default,org.eclipse.team.cvs.ssh2@default:default,org.eclipse.jdt.compiler.tool@default:false,org.eclipse.ui.ide.application@default:default,org.eclipse.team.core@default:default,org.eclipse.equinox.registry@default:default,org.junit4@default:default,org.eclipse.compare@default:default,org.eclipse.equinox.p2.updatesite@default:default,org.eclipse.equinox.frameworkadmin@default:default,com.api.tools.buildnotes.nl@default:false,org.eclipse.team.cvs.ssh@default:default,org.eclipse.equinox.p2.metadata.repository@default:default,org.eclipse.pde.ds.core@default:default,org.apache.ant@default:default,org.eclipse.equinox.simpleconfigurator.manipulator@default:default,org.eclipse.ecf.filetransfer@default:default,org.eclipse.search@default:default,org.eclipse.ui.ide@default:default,org.eclipse.ecf.provider.filetransfer.httpclient@default:default,org.eclipse.equinox.p2.touchpoint.natives@default:default,org.eclipse.equinox.p2.jarprocessor@default:default,org.apache.commons.httpclient@default:default,org.eclipse.jdt.compiler.apt@default:false,org.eclipse.ltk.core.refactoring@default:default,org.eclipse.ui.intro@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.core.resources@default:default,javax.servlet@default:default,org.eclipse.equinox.p2.engine@default:default,org.eclipse.equinox.p2.exemplarysetup@default:default,org.eclipse.ui@default:default,org.eclipse.jsch.ui@default:default,org.eclipse.pde.ua.core@default:default,org.eclipse.ecf.provider.filetransfer.ssl@default:false,org.eclipse.equinox.preferences@default:default,org.eclipse.core.net.linux.x86@default:false,javax.servlet.jsp@default:default,org.eclipse.equinox.p2.artifact.repository@default:default,com.ibm.icu@default:default,org.eclipse.core.boot@default:default,org.eclipse.jdt.apt.core@default:default,org.eclipse.osgi.util@default:default,org.eclipse.ui.editors@default:default,org.eclipse.ui.workbench.compatibility@default:false,org.eclipse.equinox.launcher@default:default,org.apache.lucene.analysis@default:default,org.eclipse.equinox.http.registry@default:default,org.eclipse.equinox.http.jetty@default:default,org.apache.commons.el@default:default,org.eclipse.equinox.launcher.gtk.linux.x86@default:false,org.eclipse.ui.presentations.r21@default:default,org.eclipse.jdt.core.manipulation@default:default,org.eclipse.equinox.app@default:default,org.eclipse.ui.cheatsheets@default:default,org.eclipse.ecf.identity@default:default,org.eclipse.swt.gtk.linux.x86@default:false,org.eclipse.update.configurator@default:default,org.eclipse.osgi@default:default,org.eclipse.jdt.apt.pluggable.core@default:default,org.eclipse.jdt.apt.ui@default:default,org.eclipse.ui.navigator@default:default,org.eclipse.pde.ua.ui@default:default,org.eclipse.jface.databinding@default:default,org.eclipse.team.cvs.ui@default:default,org.eclipse.help.webapp@default:default,org.eclipse.ecf.ssl@default:false,org.eclipse.equinox.p2.ui@default:default,org.objectweb.asm@default:default,org.sat4j.core@default:default,org.eclipse.equinox.p2.reconciler.dropins@default:default,org.eclipse.team.ui@default:default,org.eclipse.ui.browser@default:default,org.eclipse.ecf@default:default,org.eclipse.update.core.linux@default:false,org.eclipse.jdt@default:default,org.eclipse.jdt.junit@default:default,org.eclipse.equinox.p2.extensionlocation@default:default,org.eclipse.equinox.p2.metadata@default:default,org.apache.lucene@default:default,org.eclipse.ui.views.properties.tabbed@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.jobs@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.equinox.simpleconfigurator@default:default,org.eclipse.equinox.p2.core@default:default"/>

+<stringAttribute key="selected_target_plugins" value="org.eclipse.team.cvs.core@default:default,com.jcraft.jsch@default:default,org.eclipse.core.commands@default:default,org.eclipse.ltk.ui.refactoring@default:default,org.apache.jasper@default:default,org.eclipse.equinox.frameworkadmin.equinox@default:default,org.eclipse.core.databinding.beans@default:default,org.eclipse.jsch.core@default:default,org.eclipse.equinox.p2.updatechecker@default:default,org.eclipse.equinox.p2.ui.sdk@default:default,org.eclipse.help@default:default,org.eclipse.ui.net@default:default,org.eclipse.ui.intro.universal@default:default,org.eclipse.help.base@default:default,org.eclipse.equinox.p2.garbagecollector@default:default,org.mortbay.jetty.util@default:default,org.eclipse.equinox.security.ui@default:default,org.eclipse.equinox.p2.metadata.generator@default:default,org.eclipse.core.filesystem.linux.x86@default:false,org.sat4j.pb@default:default,org.eclipse.platform@default:default,org.eclipse.equinox.jsp.jasper@default:default,org.eclipse.pde.ds.ui@default:default,org.apache.commons.logging@default:default,org.eclipse.equinox.common@default:default,org.eclipse.pde@default:default,org.eclipse.core.resources.compatibility@default:false,org.eclipse.core.net@default:default,org.eclipse.core.filebuffers@default:default,org.eclipse.equinox.p2.directorywatcher@default:default,org.eclipse.equinox.security@default:default,org.eclipse.core.filesystem@default:default,org.eclipse.rcp@default:default,org.eclipse.ecf.provider.filetransfer.httpclient.ssl@default:false,org.eclipse.equinox.p2.console@default:default,org.eclipse.sdk@default:default,org.eclipse.swt@default:default,org.eclipse.ui.views@default:default,org.apache.commons.codec@default:default,org.eclipse.core.databinding@default:default,org.eclipse.ui.workbench.texteditor@default:default,org.eclipse.equinox.jsp.jasper.registry@default:default,org.eclipse.compare.core@default:default,org.eclipse.equinox.p2.touchpoint.eclipse@default:default,org.eclipse.core.expressions@default:default,org.eclipse.equinox.p2.director@default:default,org.eclipse.ui.workbench@default:default,org.eclipse.jdt.junit4.runtime@default:default,org.eclipse.jdt.junit.runtime@default:default,org.eclipse.ui.forms@default:default,org.eclipse.equinox.p2.publisher@default:default,org.eclipse.ui.navigator.resources@default:default,org.eclipse.osgi.services@default:default,org.eclipse.help.appserver@default:default,org.mortbay.jetty.server@default:default,org.junit@default:default,org.eclipse.equinox.p2.director.app@default:default,org.eclipse.equinox.p2.ui.sdk.scheduler@default:default,org.eclipse.cvs@default:default,org.eclipse.ecf.provider.filetransfer@default:default,org.eclipse.jface.text@default:default,org.eclipse.team.cvs.ssh2@default:default,org.eclipse.jdt.compiler.tool@default:false,org.eclipse.ui.ide.application@default:default,org.eclipse.team.core@default:default,org.eclipse.equinox.registry@default:default,org.junit4@default:default,org.eclipse.compare@default:default,org.eclipse.equinox.p2.updatesite@default:default,org.eclipse.equinox.frameworkadmin@default:default,com.api.tools.buildnotes.nl@default:false,org.eclipse.team.cvs.ssh@default:default,org.eclipse.equinox.p2.metadata.repository@default:default,org.eclipse.pde.ds.core@default:default,org.apache.ant@default:default,org.eclipse.equinox.simpleconfigurator.manipulator@default:default,org.eclipse.ecf.filetransfer@default:default,org.eclipse.search@default:default,org.eclipse.ui.ide@default:default,org.eclipse.ecf.provider.filetransfer.httpclient@default:default,org.eclipse.equinox.p2.touchpoint.natives@default:default,org.eclipse.equinox.p2.jarprocessor@default:default,org.apache.commons.httpclient@default:default,org.eclipse.jdt.compiler.apt@default:false,org.eclipse.ltk.core.refactoring@default:default,org.eclipse.ui.intro@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.core.resources@default:default,javax.servlet@default:default,org.eclipse.equinox.p2.engine@default:default,org.eclipse.equinox.p2.exemplarysetup@default:default,org.eclipse.ui@default:default,org.eclipse.jsch.ui@default:default,org.eclipse.pde.ua.core@default:default,org.eclipse.ecf.provider.filetransfer.ssl@default:false,org.eclipse.equinox.preferences@default:default,org.eclipse.core.net.linux.x86@default:false,javax.servlet.jsp@default:default,org.eclipse.equinox.p2.artifact.repository@default:default,com.ibm.icu@default:default,org.eclipse.core.boot@default:default,org.eclipse.jdt.apt.core@default:default,org.eclipse.osgi.util@default:default,org.eclipse.ui.editors@default:default,org.eclipse.ui.workbench.compatibility@default:false,org.eclipse.equinox.launcher@default:default,org.apache.lucene.analysis@default:default,org.eclipse.equinox.http.registry@default:default,org.eclipse.equinox.http.jetty@default:default,org.apache.commons.el@default:default,org.eclipse.equinox.launcher.gtk.linux.x86@default:false,org.eclipse.ui.presentations.r21@default:default,org.eclipse.jdt.core.manipulation@default:default,org.eclipse.equinox.app@default:default,org.eclipse.ui.cheatsheets@default:default,org.eclipse.ecf.identity@default:default,org.eclipse.swt.gtk.linux.x86@default:false,org.eclipse.osgi@default:default,org.eclipse.jdt.apt.pluggable.core@default:default,org.eclipse.jdt.apt.ui@default:default,org.eclipse.ui.navigator@default:default,org.eclipse.pde.ua.ui@default:default,org.eclipse.jface.databinding@default:default,org.eclipse.team.cvs.ui@default:default,org.eclipse.help.webapp@default:default,org.eclipse.ecf.ssl@default:false,org.eclipse.equinox.p2.ui@default:default,org.objectweb.asm@default:default,org.sat4j.core@default:default,org.eclipse.equinox.p2.reconciler.dropins@default:default,org.eclipse.team.ui@default:default,org.eclipse.ui.browser@default:default,org.eclipse.ecf@default:default,org.eclipse.jdt@default:default,org.eclipse.jdt.junit@default:default,org.eclipse.equinox.p2.extensionlocation@default:default,org.eclipse.equinox.p2.metadata@default:default,org.apache.lucene@default:default,org.eclipse.ui.views.properties.tabbed@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.jobs@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.equinox.simpleconfigurator@default:default,org.eclipse.equinox.p2.core@default:default"/>

 <stringAttribute key="selected_workspace_plugins" value="org.eclipse.jdt.core.tests.compiler@default:default,org.eclipse.example.mixedmode@default:default,org.eclipse.debug.examples.ui@default:default,org.eclipse.ant.core@default:default,org.eclipse.platform.doc.isv@default:default,org.eclipse.ant.ui@default:default,org.eclipse.jdt.core.tests.builder@default:default,org.eclipse.debug.util@default:default,org.eclipse.platform.doc.user@default:default,com.api.tools.buildnotes.nl@default:false,org.eclipse.jdt.doc.isv@default:default,org.eclipse.ui.console@default:default,org.eclipse.debug.ui@default:default,org.eclipse.pde.api.tools@default:default,org.eclipse.ui.externaltools@default:default,org.eclipse.jdt.ui.examples.javafamily@default:default,org.eclipse.pde.doc.user@default:default,org.eclipse.jdt.debug.ui@default:default,org.eclipse.jdt.doc.user@default:default,org.eclipse.jdt.debug.tests@default:default,org.eclipse.debug.examples.core@default:default,org.eclipse.jdt.core@default:default,org.eclipse.jdt.launching@default:default,refproject@default:default,org.eclipse.ant.tests.ui@default:default,org.eclipse.debug.core@default:default,org.eclipse.ant.tests.core@default:default,org.eclipse.core.variables@default:default,Testing@default:default,com.api.tools.buildnotes@default:default,org.eclipse.test.performance@default:default,org.eclipse.jdt.debug@default:default,org.eclipse.pde.api.tools.ui@default:default,usagetests@default:default,org.eclipse.pde.api.tools.tests@default:default"/>

 <booleanAttribute key="show_selected_only" value="false"/>

 <booleanAttribute key="tracing" value="false"/>

diff --git a/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF
index 9d734a4..f3fc911 100644
--- a/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.debug.tests; singleton:=true
-Bundle-Version: 3.11.50.qualifier
+Bundle-Version: 3.11.100.qualifier
 Bundle-ClassPath: javadebugtests.jar
 Bundle-Activator: org.eclipse.jdt.debug.testplugin.JavaTestPlugin
 Bundle-Vendor: %providerName
@@ -52,3 +52,4 @@
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Eclipse-BundleShape: dir
+Automatic-Module-Name: org.eclipse.jdt.debug.tests
diff --git a/org.eclipse.jdt.debug.tests/forceQualifierUpdate.txt b/org.eclipse.jdt.debug.tests/forceQualifierUpdate.txt
new file mode 100644
index 0000000..d556d7f
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/forceQualifierUpdate.txt
@@ -0,0 +1,2 @@
+# To force a version qualifier update, add the bug here
+Bug 530709 - Comparator errors in jdt debug and jdt ui in I20180204-2000
diff --git a/org.eclipse.jdt.debug.tests/java7/ThreadNameChange.java b/org.eclipse.jdt.debug.tests/java7/ThreadNameChange.java
new file mode 100644
index 0000000..ab0ea93
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java7/ThreadNameChange.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Andrey Loskutov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.TransferQueue;
+
+public class ThreadNameChange {
+
+	public static void main(String[] args) throws Exception {
+		final TransferQueue queue = new LinkedTransferQueue();
+
+		Thread t = new Thread(new Runnable() {
+			public void run() {
+				Thread thread = Thread.currentThread();
+				try {
+					queue.transfer("");
+
+					thread.setName("2");
+
+					// give debugger time to check the name
+					queue.transfer("");
+				} catch (InterruptedException e) {
+				}
+			}
+		}, "1");
+		t.start();
+
+		// wait for thread to start, debugger should see "1" at this breakpoint
+		queue.take();  // <-- bp 1
+		System.out.println("thread name: " + t.getName());
+
+		// second breakpoint, debugger should see "2" as thread name
+		queue.take(); // <-- bp 2
+		System.out.println("thread name: " + t.getName());
+	}
+}
diff --git a/org.eclipse.jdt.debug.tests/java8/DebugHoverTest18.java b/org.eclipse.jdt.debug.tests/java8/DebugHoverTest18.java
new file mode 100644
index 0000000..9c0b242
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/java8/DebugHoverTest18.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ *  Copyright (c) 2017 Andrey Loskutov and others.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+public class DebugHoverTest18 {
+
+	public static void main(String[] args) {
+		new DebugHoverTest18().run("Hello");
+	}
+
+	private void run(String arg) {
+		Object var1 = "v0";
+		int var2 = 2;
+		String [][] var3 = null;
+		Long[] args = null;
+		run(var1, var2, var3, args);
+	}
+
+	private void run(Object arg, int i, String [][] args, Long...objects) {
+		String var1 = "v1";
+		run(()->{
+			String var2 = "v2";
+			System.out.println(var2);
+			System.out.println(var1);
+			System.out.println(arg);
+
+			run(()->{
+				String var3 = "v2";
+				System.out.println(var2);
+				System.out.println(var3);
+				System.out.println(var1);
+				System.out.println(arg);
+			});
+		});
+	}
+
+	/*
+	 * Variables below to check if we don't resolve to wrong frame
+	 */
+	@SuppressWarnings("unused")
+	static void run(Runnable r) {
+		int var1 = 1;
+		int var2 = 2;
+		int var3 = 3;
+		int arg = 4;
+		r.run();
+	}
+}
diff --git a/org.eclipse.jdt.debug.tests/pom.xml b/org.eclipse.jdt.debug.tests/pom.xml
index 5fe7a80..7ad17c8 100644
--- a/org.eclipse.jdt.debug.tests/pom.xml
+++ b/org.eclipse.jdt.debug.tests/pom.xml
@@ -14,11 +14,11 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.3-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.debug.tests</artifactId>
-  <version>3.11.50-SNAPSHOT</version>
+  <version>3.11.100-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
   <properties>
     <code.ignoredWarnings>${tests.ignoredWarnings}</code.ignoredWarnings>
diff --git a/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/GlobalBreakpointListener.java b/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/GlobalBreakpointListener.java
index 1d03e79..0bbf60c 100644
--- a/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/GlobalBreakpointListener.java
+++ b/org.eclipse.jdt.debug.tests/test plugin/org/eclipse/jdt/debug/testplugin/GlobalBreakpointListener.java
@@ -10,6 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.debug.testplugin;
 
+import java.util.LinkedHashSet;
+import java.util.Set;
+
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.jdt.core.dom.Message;
 import org.eclipse.jdt.debug.core.IJavaBreakpoint;
@@ -24,18 +27,18 @@
  */
 public class GlobalBreakpointListener implements IJavaBreakpointListener {
 
-	public static IJavaBreakpoint ADDED;
-	public static IJavaBreakpoint HIT;
-	public static IJavaBreakpoint INSTALLED;
-	public static IJavaBreakpoint REMOVED;
-	public static IJavaBreakpoint INSTALLING;
+	public static Set<IJavaBreakpoint> ADDED = new LinkedHashSet<>();
+	public static Set<IJavaBreakpoint> HIT = new LinkedHashSet<>();
+	public static Set<IJavaBreakpoint> INSTALLED = new LinkedHashSet<>();
+	public static Set<IJavaBreakpoint> REMOVED = new LinkedHashSet<>();
+	public static Set<IJavaBreakpoint> INSTALLING = new LinkedHashSet<>();
 
 	public static void clear() {
-		ADDED = null;
-		HIT = null;
-		INSTALLED = null;
-		REMOVED = null;
-		INSTALLING = null;
+		ADDED.clear();
+		HIT.clear();
+		INSTALLED.clear();
+		REMOVED.clear();
+		INSTALLING.clear();
 	}
 
 	public GlobalBreakpointListener() {
@@ -43,7 +46,7 @@
 
 	@Override
 	public void addingBreakpoint(IJavaDebugTarget target, IJavaBreakpoint breakpoint) {
-		ADDED = breakpoint;
+		ADDED.add(breakpoint);
 	}
 
 	@Override
@@ -56,23 +59,23 @@
 
 	@Override
 	public int breakpointHit(IJavaThread thread, IJavaBreakpoint breakpoint) {
-		HIT = breakpoint;
+		HIT.add(breakpoint);
 		return DONT_CARE;
 	}
 
 	@Override
 	public void breakpointInstalled(IJavaDebugTarget target, IJavaBreakpoint breakpoint) {
-		INSTALLED = breakpoint;
+		INSTALLED.add(breakpoint);
 	}
 
 	@Override
 	public void breakpointRemoved(IJavaDebugTarget target, IJavaBreakpoint breakpoint) {
-		REMOVED = breakpoint;
+		REMOVED.add(breakpoint);
 	}
 
 	@Override
 	public int installingBreakpoint(IJavaDebugTarget target, IJavaBreakpoint breakpoint, IJavaType type) {
-		INSTALLING = breakpoint;
+		INSTALLING.add(breakpoint);
 		return DONT_CARE;
 	}
 
diff --git a/org.eclipse.jdt.debug.tests/testprograms/BulkThreadCreationTest.java b/org.eclipse.jdt.debug.tests/testprograms/BulkThreadCreationTest.java
new file mode 100644
index 0000000..ca0dad1
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/BulkThreadCreationTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2017 salesforce.com.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     salesforce.com - initial API and implementation
+ *******************************************************************************/
+
+public class BulkThreadCreationTest {
+
+	public static void main(String[] args) throws Exception {
+		int count = 1000;
+		Thread[] threads = new Thread[count];
+		for (int i = 0; i < count; i++) {
+			threads[i] = new Thread("bulk-" + i);
+			threads[i].start();
+		}
+		for (int i = 0; i < count; i++) {
+			threads[i].join();
+		}
+		return;
+	}
+
+}
diff --git a/org.eclipse.jdt.debug.tests/testprograms/MethodExitAndException.java b/org.eclipse.jdt.debug.tests/testprograms/MethodExitAndException.java
new file mode 100644
index 0000000..fde01b7
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/MethodExitAndException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Till Brychcy and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Till Brychcy - initial API and implementation
+ *******************************************************************************/
+
+class MyException extends Exception {
+
+    public final int value;
+
+    public MyException(int value) {
+        this.value = value;
+    }
+}
+
+public class MethodExitAndException {
+    public static void main(String[] args) {
+        int x = f();
+        try {
+            g(x);
+        } catch (MyException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static int f() {
+        return 123;
+    }
+
+    private static void g(int i) throws MyException {
+        throw new MyException(i);
+    }
+}
diff --git a/org.eclipse.jdt.debug.tests/testprograms/StepUncaught.java b/org.eclipse.jdt.debug.tests/testprograms/StepUncaught.java
new file mode 100644
index 0000000..c5191e2
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/StepUncaught.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Till Brychcy and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Till Brychcy - initial API and implementation
+ *******************************************************************************/
+
+public class StepUncaught {
+	public static void main(String[] args) {
+		try {
+			f(); // bp
+		} catch (Throwable e) {
+		}
+		g();
+	}
+
+	private static void f() {
+		throw new RuntimeException("caught");
+	}
+	private static void g() {
+		throw new RuntimeException("uncaught");
+	}
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/test/stepping/StepResultTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/test/stepping/StepResultTests.java
index 82df334..08afb03 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/test/stepping/StepResultTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/test/stepping/StepResultTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016 Till Brychcy and others.
+ * Copyright (c) 2017 Till Brychcy and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,11 +14,16 @@
 import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IVariable;
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
 import org.eclipse.jdt.debug.core.IJavaObject;
 import org.eclipse.jdt.debug.core.IJavaStackFrame;
 import org.eclipse.jdt.debug.core.IJavaThread;
 import org.eclipse.jdt.debug.core.IJavaValue;
 import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.internal.debug.ui.IJDIPreferencesConstants;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
 
 public class StepResultTests extends AbstractDebugTest {
 
@@ -44,7 +49,6 @@
 			assertEquals("h() returned", varInG.getName());
 			assertEquals("\"h-i\"", varInG.getValue().toString());
 
-
 			// skip the synthetic via a step filter.
 			IJavaDebugTarget javaDebugTarget = (IJavaDebugTarget) stackFrame.getDebugTarget();
 			boolean oldStepFiltersEnabled = javaDebugTarget.isStepFiltersEnabled();
@@ -470,4 +474,65 @@
 		}
 	}
 
+	public void testStepUncaught() throws Exception {
+		IPreferenceStore preferenceStore = JDIDebugUIPlugin.getDefault().getPreferenceStore();
+		boolean origPrefValue = preferenceStore.getBoolean(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS);
+		preferenceStore.setValue(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, true);
+		String typeName = "StepUncaught";
+		ILineBreakpoint bp = createLineBreakpoint(15, "StepUncaught");
+		bp.setEnabled(true);
+
+		IJavaThread thread = null;
+		try {
+			thread = launchAndSuspend(typeName);
+			IJavaStackFrame stackFrame = (IJavaStackFrame) thread.getTopStackFrame();
+			assertEquals("main", stackFrame.getMethodName());
+
+			stepOver(stackFrame);
+
+			stackFrame = (IJavaStackFrame) thread.getTopStackFrame();
+			assertEquals("main", stackFrame.getMethodName());
+			assertEquals("f() threw", stackFrame.getVariables()[0].getName());
+
+			stepOverToBreakpoint(stackFrame);
+
+			stackFrame = (IJavaStackFrame) thread.getTopStackFrame();
+			assertEquals("g", stackFrame.getMethodName());
+		}
+		finally {
+			preferenceStore.setValue(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, origPrefValue);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+
+	public void testMethodResultOnMethodExitAndExceptionBreakpoints() throws Exception {
+		IPreferenceStore preferenceStore = JDIDebugUIPlugin.getDefault().getPreferenceStore();
+		boolean origPrefValue = preferenceStore.getBoolean(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS);
+		preferenceStore.setValue(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, true);
+		String typeName = "MethodExitAndException";
+		IJavaMethodBreakpoint methodExitBreakpoint = createMethodBreakpoint("MethodExitAndException", "f", null, false, true);
+		IJavaExceptionBreakpoint exceptionBreakpoint = createExceptionBreakpoint("MyException", true, true);
+		methodExitBreakpoint.setEnabled(true);
+		exceptionBreakpoint.setEnabled(true);
+		IJavaThread thread = null;
+		try {
+			thread = launchAndSuspend(typeName);
+			IJavaStackFrame stackFrame = (IJavaStackFrame) thread.getTopStackFrame();
+			assertEquals("f", stackFrame.getMethodName());
+			assertEquals("f() is returning", stackFrame.getVariables()[0].getName());
+
+			resume(thread);
+
+			stackFrame = (IJavaStackFrame) thread.getTopStackFrame();
+			assertEquals("g", stackFrame.getMethodName());
+			assertEquals("g() is throwing", stackFrame.getVariables()[0].getName());
+		}
+		finally {
+			preferenceStore.setValue(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, origPrefValue);
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+
 }
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
index 76e36a8..554ec18 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -197,9 +198,7 @@
 			"bug329294", "bug401270", "org.eclipse.debug.tests.targets.HcrClass2", "org.eclipse.debug.tests.targets.HcrClass3", "org.eclipse.debug.tests.targets.HcrClass4",
 			"org.eclipse.debug.tests.targets.HcrClass5", "org.eclipse.debug.tests.targets.HcrClass6", "org.eclipse.debug.tests.targets.HcrClass7", "org.eclipse.debug.tests.targets.HcrClass8",
 			"org.eclipse.debug.tests.targets.HcrClass9", "TestContributedStepFilterClass", "TerminateAll_01", "TerminateAll_02", "StepResult1",
-			"StepResult2", "StepResult3", "TriggerPoint_01" };
-
-	final String[] LAUNCH_CONFIG_NAMES_1_8 = {"LargeSourceFile"};
+			"StepResult2", "StepResult3", "StepUncaught", "TriggerPoint_01", "BulkThreadCreationTest", "MethodExitAndException" };
 
 	/**
 	 * the default timeout
@@ -427,6 +426,7 @@
 	        if (!loaded17) {
 	        	jp = createProject(ONE_SEVEN_PROJECT_NAME, JavaProjectHelper.TEST_1_7_SRC_DIR.toString(), JavaProjectHelper.JAVA_SE_1_7_EE_NAME, false);
 	    		cfgs.add(createLaunchConfiguration(jp, LiteralTests17.LITERAL_TYPE_NAME));
+				cfgs.add(createLaunchConfiguration(jp, "ThreadNameChange"));
 	    		loaded17 = true;
 	    		waitForBuild();
 	        }
@@ -459,6 +459,7 @@
 	    		cfgs.add(createLaunchConfiguration(jp, "EvalTest18"));
 	    		cfgs.add(createLaunchConfiguration(jp, "EvalTestIntf18"));
 				cfgs.add(createLaunchConfiguration(jp, "EvalIntfSuperDefault"));
+				cfgs.add(createLaunchConfiguration(jp, "DebugHoverTest18"));
 	    		loaded18 = true;
 	    		waitForBuild();
 	        }
@@ -475,7 +476,7 @@
         	catch (CoreException ce) {
         		//ignore
 			}
-			handleProjectCreationException(e, ONE_SEVEN_PROJECT_NAME, jp);
+			handleProjectCreationException(e, ONE_EIGHT_PROJECT_NAME, jp);
         }
 	}
 
@@ -2474,6 +2475,7 @@
 		ILaunchConfigurationWorkingCopy config = type.newInstance(project.getProject().getFolder(LAUNCHCONFIGURATIONS), configName);
         config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, mainTypeName);
         config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getElementName());
+        setEnvironment(config);
 		Set<String> modes = new HashSet<>();
 		modes.add(ILaunchManager.RUN_MODE);
 		config.setPreferredLaunchDelegate(modes, LOCAL_JAVA_APPLICATION_TYPE_ID);
@@ -2496,6 +2498,7 @@
         ILaunchConfigurationWorkingCopy config = type.newInstance(project.getProject().getFolder(containername), mainTypeName);
         config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, mainTypeName);
         config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getElementName());
+        setEnvironment(config);
 		Set<String> modes = new HashSet<>();
 		modes.add(ILaunchManager.RUN_MODE);
 		config.setPreferredLaunchDelegate(modes, LOCAL_JAVA_APPLICATION_TYPE_ID);
@@ -2510,6 +2513,14 @@
         return config.doSave();
     }
 
+    private void setEnvironment(ILaunchConfigurationWorkingCopy workingCopy) {
+      Map<String, String> env = getLaunchManager().getNativeEnvironment().entrySet().stream()
+        .filter(e -> !"JAVA_TOOL_OPTIONS".equals(e.getKey()))
+        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+      workingCopy.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, false);
+      workingCopy.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, env);
+    }
+
 	/**
 	 * When a test throws the 'try again' exception, try it again.
 	 * @see junit.framework.TestCase#runBare()
@@ -2780,4 +2791,3 @@
 	}
 
 }
-
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index 6237810..852bdc2 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -39,6 +39,7 @@
 import org.eclipse.jdt.debug.tests.breakpoints.TestToggleBreakpointsTarget;
 import org.eclipse.jdt.debug.tests.breakpoints.TestToggleBreakpointsTarget8;
 import org.eclipse.jdt.debug.tests.breakpoints.ThreadFilterBreakpointsTests;
+import org.eclipse.jdt.debug.tests.breakpoints.ThreadNameChangeTests;
 import org.eclipse.jdt.debug.tests.breakpoints.TriggerPointBreakpointsTests;
 import org.eclipse.jdt.debug.tests.breakpoints.TypeNameBreakpointTests;
 import org.eclipse.jdt.debug.tests.breakpoints.WatchpointTests;
@@ -58,6 +59,7 @@
 import org.eclipse.jdt.debug.tests.core.DebugEventTests;
 import org.eclipse.jdt.debug.tests.core.EEDefinitionTests;
 import org.eclipse.jdt.debug.tests.core.EnvironmentTests;
+import org.eclipse.jdt.debug.tests.core.EventDispatcherTest;
 import org.eclipse.jdt.debug.tests.core.EventSetTests;
 import org.eclipse.jdt.debug.tests.core.ExecutionEnvironmentTests;
 import org.eclipse.jdt.debug.tests.core.HcrTests;
@@ -117,7 +119,7 @@
 import org.eclipse.jdt.debug.tests.sourcelookup.SourceLookupTests;
 import org.eclipse.jdt.debug.tests.sourcelookup.TypeResolutionTests;
 import org.eclipse.jdt.debug.tests.state.RefreshStateTests;
-import org.eclipse.jdt.debug.tests.ui.DebugViewTests;
+import org.eclipse.jdt.debug.tests.ui.DebugHoverTests;
 import org.eclipse.jdt.debug.tests.ui.DetailPaneManagerTests;
 import org.eclipse.jdt.debug.tests.ui.OpenFromClipboardTests;
 import org.eclipse.jdt.debug.tests.ui.ViewManagementTests;
@@ -190,6 +192,7 @@
 		addTest(new TestSuite(BreakpointListenerTests.class));
 		addTest(new TestSuite(JavaBreakpointListenerTests.class));
 		addTest(new TestSuite(MiscBreakpointsTests.class));
+		addTest(new TestSuite(ThreadNameChangeTests.class));
 		addTest(new TestSuite(BreakpointLocationVerificationTests.class));
 		addTest(new TestSuite(RunToLineTests.class));
 		addTest(new TestSuite(TestToggleBreakpointsTarget.class));
@@ -279,6 +282,7 @@
 		addTest(new TestSuite(StratumTests.class));
 		addTest(new TestSuite(JavaDebugTargetTests.class));
 		addTest(new TestSuite(WorkingDirectoryTests.class));
+		addTest(new TestSuite(EventDispatcherTest.class));
 
 	// Refactoring tests
 		//TODO: project rename
@@ -321,7 +325,11 @@
 		addTest(new TestSuite(ViewManagementTests.class));
 
 	// Debug view tests
-		addTest(new TestSuite(DebugViewTests.class));
+		// Test is not stable, see bug 516024
+		// addTest(new TestSuite(DebugViewTests.class));
+
+	// Debug hover tests
+		addTest(new TestSuite(DebugHoverTests.class));
 
 	// Leak tests
 		addTest(new TestSuite(InstructionPointerTests.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsTests.java
index dd843de..e204929 100755
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ConditionalBreakpointsTests.java
@@ -210,7 +210,10 @@
 			assertNotNull("Missing top frame", frame);
 			assertEquals("Wrong location", "calculateSum", frame.getName());
 			thread.resume();
-			assertFalse("Thread should be resumed", thread.isSuspended());
+			Thread.sleep(300);
+			// TODO: see bug 519382 - [tests] testSuspendLongRunningCondition: thread sporadically stays suspended
+			// For whatever reason we sometimes see that thread is not resumed.
+			// assertFalse("Thread should be resumed", thread.isSuspended());
 		} finally {
 			terminateAndRemove(thread);
 			removeAllBreakpoints();
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/JavaBreakpointListenerTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/JavaBreakpointListenerTests.java
index 4fdc793..240e21a 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/JavaBreakpointListenerTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/JavaBreakpointListenerTests.java
@@ -171,9 +171,9 @@
 	 */
 	class Collector implements IJavaBreakpointListener {
 
-		public List<IJavaBreakpoint> HIT = new ArrayList<IJavaBreakpoint>();
-		public List<IJavaLineBreakpoint> COMPILATION_ERRORS = new ArrayList<IJavaLineBreakpoint>();
-		public List<IJavaLineBreakpoint> RUNTIME_ERRORS = new ArrayList<IJavaLineBreakpoint>();
+		public List<IJavaBreakpoint> HIT = new ArrayList<>();
+		public List<IJavaLineBreakpoint> COMPILATION_ERRORS = new ArrayList<>();
+		public List<IJavaLineBreakpoint> RUNTIME_ERRORS = new ArrayList<>();
 
 		@Override
 		public void addingBreakpoint(IJavaDebugTarget target, IJavaBreakpoint breakpoint) {
@@ -989,14 +989,14 @@
 		try {
 			thread= launchToLineBreakpoint(typeName, bp);
 
-			assertEquals("Should be ADDED", bp, GlobalBreakpointListener.ADDED);
-			assertEquals("Should be INSTALLING", bp, GlobalBreakpointListener.INSTALLING);
-			assertEquals("Should be INSTALLED", bp, GlobalBreakpointListener.INSTALLED);
-			assertEquals("Should be HIT", bp, GlobalBreakpointListener.HIT);
-			assertNull("Should not be REMOVED", GlobalBreakpointListener.REMOVED);
+			assertTrue("Should be ADDED", GlobalBreakpointListener.ADDED.contains(bp));
+			assertTrue("Should be INSTALLING", GlobalBreakpointListener.INSTALLING.contains(bp));
+			assertTrue("Should be INSTALLED", GlobalBreakpointListener.INSTALLED.contains(bp));
+			assertTrue("Should be HIT", GlobalBreakpointListener.HIT.contains(bp));
+			assertFalse("Should not be REMOVED", GlobalBreakpointListener.REMOVED.contains(bp));
 
 			bp.delete();
-			assertEquals("Should be REMOVED", bp, GlobalBreakpointListener.REMOVED);
+			assertTrue("Should be REMOVED", GlobalBreakpointListener.REMOVED.contains(bp));
 		} finally {
 			terminateAndRemove(thread);
 			removeAllBreakpoints();
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ThreadNameChangeTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ThreadNameChangeTests.java
new file mode 100644
index 0000000..de4d889
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/ThreadNameChangeTests.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ *  Copyright (c) 2018 Andrey Loskutov <loskutov@gmx.de>.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.breakpoints;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.debug.tests.TestUtil;
+import org.eclipse.jdt.internal.debug.ui.IJDIPreferencesConstants;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Home for breakpoint tests related to thread name change events
+ */
+public class ThreadNameChangeTests extends AbstractDebugTest {
+
+	/**
+	 * Constructor
+	 * @param name
+	 */
+	public ThreadNameChangeTests(String name) {
+		super(name);
+	}
+
+	/**
+	 * Tests that we listen to thread name changes and send a debug event if that happens
+	 *
+	 * @throws Exception
+	 */
+	public void testListenToThreadNameChange() throws Exception {
+		String typeName = "ThreadNameChange";
+		final int bpLine1 = 36;
+		final int bpLine2 = 40;
+
+		IJavaLineBreakpoint bp1 = createLineBreakpoint(bpLine1, "", typeName + ".java", typeName);
+		IJavaLineBreakpoint bp2 = createLineBreakpoint(bpLine2, "", typeName + ".java", typeName);
+		bp1.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+		bp2.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+		boolean oldValue = getPrefStore().getBoolean(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES);
+		getPrefStore().setValue(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES, true);
+		AtomicReference<List<DebugEvent>> events = new AtomicReference<>(new ArrayList<DebugEvent>());
+		IDebugEventSetListener listener = new IDebugEventSetListener() {
+			@Override
+			public void handleDebugEvents(DebugEvent[] e) {
+				events.get().addAll(Arrays.asList(e));
+			}
+		};
+		DebugPlugin.getDefault().addDebugEventListener(listener);
+		IJavaThread thread = null;
+		try {
+			thread = launchToLineBreakpoint(typeName, bp1);
+			TestUtil.waitForJobs(getName(), 100, 3000);
+
+			// expect that thread with name "1" is started
+			IThread second = findThread(thread, "1");
+			assertNotNull(second);
+			events.get().clear();
+
+			resumeToLineBreakpoint(thread, bp2);
+			TestUtil.waitForJobs(getName(), 100, 3000);
+
+			// expect one single "CHANGE" event for second thread
+			List<DebugEvent> changeEvents = getStateChangeEvents(events, second);
+			assertEquals(1, changeEvents.size());
+
+			// expect that thread name is changed to "2"
+			assertEquals("2", second.getName());
+		}
+		finally {
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+			DebugPlugin.getDefault().removeDebugEventListener(listener);
+			getPrefStore().setValue(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES, oldValue);
+		}
+	}
+
+	/**
+	 * Tests that we do not listen to thread name changes if the corresponding preference is set to false
+	 *
+	 * @throws Exception
+	 */
+	public void testListenToThreadNameChangeDisabled() throws Exception {
+		String typeName = "ThreadNameChange";
+		final int bpLine1 = 36;
+		final int bpLine2 = 40;
+
+		IJavaLineBreakpoint bp1 = createLineBreakpoint(bpLine1, "", typeName + ".java", typeName);
+		IJavaLineBreakpoint bp2 = createLineBreakpoint(bpLine2, "", typeName + ".java", typeName);
+		bp1.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+		bp2.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+		boolean oldValue = getPrefStore().getBoolean(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES);
+		getPrefStore().setValue(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES, false);
+		AtomicReference<List<DebugEvent>> events = new AtomicReference<>(new ArrayList<DebugEvent>());
+		IDebugEventSetListener listener = new IDebugEventSetListener() {
+			@Override
+			public void handleDebugEvents(DebugEvent[] e) {
+				events.get().addAll(Arrays.asList(e));
+			}
+		};
+		DebugPlugin.getDefault().addDebugEventListener(listener);
+		IJavaThread thread = null;
+		try {
+			thread = launchToLineBreakpoint(typeName, bp1);
+			TestUtil.waitForJobs(getName(), 100, 3000);
+
+			// expect that thread with name "1" is started
+			IThread second = findThread(thread, "1");
+			assertNotNull(second);
+			events.get().clear();
+
+			resumeToLineBreakpoint(thread, bp2);
+			TestUtil.waitForJobs(getName(), 100, 3000);
+
+			// expect no "CHANGE" events
+			List<DebugEvent> changeEvents = getStateChangeEvents(events, second);
+			assertEquals(0, changeEvents.size());
+
+			// expect that thread name is changed to "2"
+			assertEquals("2", second.getName());
+		}
+		finally {
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+			DebugPlugin.getDefault().removeDebugEventListener(listener);
+			getPrefStore().setValue(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES, oldValue);
+		}
+	}
+
+	private List<DebugEvent> getStateChangeEvents(AtomicReference<List<DebugEvent>> events, IThread second) {
+		List<DebugEvent> list = events.get();
+		Stream<DebugEvent> filtered = list.stream().filter(x -> x.getKind() == DebugEvent.CHANGE && x.getDetail() == DebugEvent.STATE
+				&& x.getSource() == second);
+		return filtered.collect(Collectors.toList());
+	}
+
+	private IThread findThread(IJavaThread thread, String name) throws DebugException {
+		IThread t = Arrays.stream(thread.getDebugTarget().getThreads()).filter(x -> {
+			try {
+				return x.getName().equals(name);
+			}
+			catch (DebugException e1) {
+			}
+			return false;
+		}).findFirst().get();
+		return t;
+	}
+
+	/**
+	 * Returns the <code>JDIDebugUIPlugin</code> preference store
+	 * @return
+	 */
+	protected IPreferenceStore getPrefStore() {
+		return JDIDebugUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	@Override
+	protected IJavaProject getProjectContext() {
+		return super.get17Project();
+	}
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ArgumentTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ArgumentTests.java
index 286cf49..d18597f 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ArgumentTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ArgumentTests.java
@@ -13,6 +13,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.runtime.CoreException;
@@ -68,7 +69,10 @@
 			try {
                 assertNotNull("received notification of invalid line", line);
                 assertNotNull("buffer is null", buffer);
-                buffer.append(document.get(line.getOffset(), line.getLength()));
+                String text = document.get(line.getOffset(), line.getLength());
+				if (!JavaOutputHelpers.isKnownExtraneousOutput(text)) {
+					buffer.append(text);
+				}
 			} catch (BadLocationException e) {
 				e.printStackTrace();
 			}
@@ -341,12 +345,19 @@
 		workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, true);
 		workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, vmArgs);
 		workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, programArgs);
+
+    Map<String, String> env = getLaunchManager().getNativeEnvironment().entrySet().stream()
+  		.filter(e -> !"JAVA_TOOL_OPTIONS".equals(e.getKey()))
+  		.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+    workingCopy.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, false);
+		workingCopy.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, env);
+
 		IVMInstall vm = JavaRuntime.getVMInstall(get14Project());
 		assertNotNull("shold be able to get the default VM install from the 1.4 project", vm);
 		//workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, JavaRuntime.newJREContainerPath(vm).toPortableString());
 
 		// use 'java' instead of 'javaw' to launch tests (javaw is problematic on JDK1.4.2)
-		Map<String, String> map = new HashMap<String, String>(1);
+		Map<String, String> map = new HashMap<>(1);
 		map.put(IJavaLaunchConfigurationConstants.ATTR_JAVA_COMMAND, "java");
 		workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, map);
 
@@ -355,7 +366,7 @@
 		IProcess process = null;
 		ILaunch launch = null;
 		try {
-			HashSet<String> set = new HashSet<String>();
+			HashSet<String> set = new HashSet<>();
 			set.add(ILaunchManager.RUN_MODE);
 			ensurePreferredDelegate(workingCopy, set);
 			launch = workingCopy.launch(ILaunchManager.RUN_MODE, null);
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ConsoleInputTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ConsoleInputTests.java
index f147e17..966c47e 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ConsoleInputTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/ConsoleInputTests.java
@@ -13,6 +13,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.core.runtime.Platform;
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchManager;
@@ -37,7 +38,7 @@
  */
 public class ConsoleInputTests extends AbstractDebugTest implements IConsoleLineTrackerExtension {
 
-	protected List<String> fLinesRead = new ArrayList<String>();
+	protected List<String> fLinesRead = new ArrayList<>();
 
 	protected boolean fStarted = false;
 
@@ -80,12 +81,7 @@
 		ILaunch launch = null;
 		try {
 			launch = configuration.launch(ILaunchManager.RUN_MODE, null);
-			synchronized (fConsoleLock) {
-				if (!fStarted) {
-					fConsoleLock.wait(30000);
-				}
-			}
-			assertNotNull("Console is null", fConsole);
+			waitStarted();
 			String[] list = appendAndGet(fConsole, "one\ntwo\nexit", 4);
 			verifyOutput(new String[]{"one", "two", "exitone", "two"}, list);
 
@@ -108,12 +104,7 @@
 		ILaunch launch = null;
 		try {
 			launch = configuration.launch(ILaunchManager.RUN_MODE, null);
-			synchronized (fConsoleLock) {
-				if (!fStarted) {
-					fConsoleLock.wait(30000);
-				}
-			}
-			assertNotNull("Console is null", fConsole);
+			waitStarted();
 			String[] list = appendAndGet(fConsole, "one\ntwo\n", 4);
 			verifyOutput(new String[]{"one", "two", "one", "two"}, list);
 
@@ -264,7 +255,9 @@
 			synchronized (fLinesRead) {
 				try {
 					String text = fConsole.getDocument().get(line.getOffset(), line.getLength());
-					fLinesRead.add(text);
+					if (!JavaOutputHelpers.isKnownExtraneousOutput(text)) {
+						fLinesRead.add(text);
+					}
 				} catch (BadLocationException e) {
 				    e.printStackTrace();
 				}
@@ -273,6 +266,20 @@
 		}
 	}
 
+	private void waitStarted() throws InterruptedException {
+		synchronized (fConsoleLock) {
+			if (!fStarted) {
+				fConsoleLock.wait(30000);
+			}
+		}
+		assertNotNull("Console is null", fConsole);
+		if (Platform.OS_MACOSX.equals(Platform.getOS())) {
+			// on OSX java process writes unexpected message to stderr due to https://bugs.openjdk.java.net/browse/JDK-8022291
+			// need to wait for the message to fully appear so it can be filtered in #lineAppended above
+			Thread.sleep(1000L);
+		}
+	}
+
 	/**
 	 * @see org.eclipse.debug.ui.console.IConsoleLineTracker#streamClosed()
 	 */
@@ -296,12 +303,7 @@
 		ILaunch launch = null;
 		try {
 			launch = configuration.launch(ILaunchManager.RUN_MODE, null);
-			synchronized (fConsoleLock) {
-				if (!fStarted) {
-					fConsoleLock.wait(30000);
-				}
-			}
-			assertNotNull("Console is null", fConsole);
+			waitStarted();
 			append(fConsole, "a");
 			deleteAll(fConsole);
 			append(fConsole, "b");
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/EventDispatcherTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/EventDispatcherTest.java
new file mode 100644
index 0000000..18a5d45
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/EventDispatcherTest.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ *  Copyright (c) 2017 salesforce.com.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *     salesforce.com - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.core;
+
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.internal.debug.core.EventDispatcher.AbstractDispatchJob;
+import org.eclipse.jdt.internal.debug.core.model.JDIThread;
+
+public class EventDispatcherTest extends AbstractDebugTest {
+
+	private JobChangeAdapter jobListener;
+	private Map<AbstractDispatchJob, Object> jobs;
+
+	public EventDispatcherTest(String name) {
+		super(name);
+	}
+
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		jobs = Collections.synchronizedMap(new IdentityHashMap<AbstractDispatchJob, Object>());
+		jobListener = new JobChangeAdapter() {
+			@Override
+			public void aboutToRun(IJobChangeEvent event) {
+				Job job = event.getJob();
+				if (job instanceof AbstractDispatchJob) {
+					jobs.put((AbstractDispatchJob) job, Boolean.TRUE);
+				}
+			}
+		};
+		Job.getJobManager().addJobChangeListener(jobListener);
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		if (jobListener != null) {
+			Job.getJobManager().removeJobChangeListener(jobListener);
+		}
+		super.tearDown();
+	}
+
+	public void test285130_bulkThreadCreation() throws Exception {
+		// the real goal of this test is to validate that rapidly delivered JDI events do not start large number of threads
+		// unfortunately there is no direct way to observe startup of the JDI event processing threads
+		// as approximation, assert single JDI processing Job was ever run during the test
+		// as sanity check, assert expected number of DebugEvent was delivered during the test
+
+		// sanity check: count number of JDIThread thread-create events
+		AtomicInteger threadCount = new AtomicInteger();
+		IDebugEventSetListener debugListener = events -> {
+			for (DebugEvent event : events) {
+				if (event.getKind() == DebugEvent.CREATE && event.getSource() instanceof JDIThread) {
+					JDIThread thread = (JDIThread) event.getSource();
+					try {
+						if (thread.getName().startsWith("bulk-")) {
+							threadCount.incrementAndGet();
+						}
+					}
+					catch (DebugException e) {
+					}
+				}
+			}
+		};
+		try {
+			DebugPlugin.getDefault().addDebugEventListener(debugListener);
+			createLineBreakpoint(24, "BulkThreadCreationTest");
+			launchToBreakpoint("BulkThreadCreationTest");
+		}
+		finally {
+			removeAllBreakpoints();
+			DebugPlugin.getDefault().removeDebugEventListener(debugListener);
+		}
+
+		assertEquals("Unexpected number of JDIThread thread-create events", 1000, threadCount.get());
+		assertEquals("Unexpected number of event dispatching jobs: " + jobs.size() + " | " + jobs.keySet(), 0, jobs.size());
+	}
+
+	/**
+	 * Tests that a conditional breakpoint with an expression that will hit a breakpoint will complete the conditional expression evaluation (bug
+	 * 269231) and that we dispatch events for conditional breakpoints in dedicated jobs.
+	 *
+	 * @throws Exception
+	 */
+	public void testConditionalExpressionEventDispatching() throws Exception {
+		String typeName = "BreakpointListenerTest";
+		createConditionalLineBreakpoint(15, typeName, "foo(); return false;", true);
+		IJavaLineBreakpoint breakpoint = createLineBreakpoint(20, typeName);
+		IJavaThread thread = null;
+		try {
+			thread = launchToLineBreakpoint(typeName, breakpoint);
+			IStackFrame top = thread.getTopStackFrame();
+			assertNotNull("Missing top frame", top);
+			assertTrue("Thread should be suspended", thread.isSuspended());
+			assertEquals("Wrong location", breakpoint.getLineNumber(), top.getLineNumber());
+		}
+		finally {
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+		// Expect to see two jobs for conditional breakpoint with 1) class prepare and 2) breakpoint hit events
+		assertEquals("Unexpected number of event dispatching jobs: " + jobs.size() + " | " + jobs.keySet(), 2, jobs.size());
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/JavaDebugTargetTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/JavaDebugTargetTests.java
index b6b3e07..24d0056 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/JavaDebugTargetTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/JavaDebugTargetTests.java
@@ -13,7 +13,9 @@
 import static org.junit.Assert.assertNotEquals;
 
 import java.lang.reflect.Method;
+import java.util.List;
 
+import org.eclipse.debug.core.model.IBreakpoint;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
@@ -21,6 +23,7 @@
 import org.eclipse.jdt.debug.core.IJavaThread;
 import org.eclipse.jdt.debug.tests.AbstractDebugTest;
 import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
+import org.eclipse.jdt.internal.debug.ui.JavaDebugOptionsManager;
 
 /**
  * Tests IJavaDebugTarget API
@@ -145,8 +148,9 @@
 			assertNotNull("Breakpoint not hit within timeout period", thread);
 			JDIDebugTarget target = (JDIDebugTarget) thread.getDebugTarget();
 			assertTrue(target.isAvailable());
-			assertEquals(1, target.getBreakpoints().size());
-			assertEquals(bp1, target.getBreakpoints().get(0));
+			List<IBreakpoint> breakpoints = getUserBreakpoints(target);
+			assertEquals(1, breakpoints.size());
+			assertEquals(bp1, getUserBreakpoints(target).get(0));
 			assertTrue(target.supportsResource(() -> typeName, type1.getResource()));
 			assertFalse(target.supportsResource(() -> typeName, type2.getResource()));
 			terminateAndRemove(thread);
@@ -161,8 +165,8 @@
 			assertNotNull("Breakpoint not hit within timeout period", thread);
 			target = (JDIDebugTarget) thread.getDebugTarget();
 			assertTrue(target.isAvailable());
-			assertEquals(1, target.getBreakpoints().size());
-			assertEquals(bp2, target.getBreakpoints().get(0));
+			assertEquals(1, getUserBreakpoints(target).size());
+			assertEquals(bp2, getUserBreakpoints(target).get(0));
 			assertFalse(target.supportsResource(() -> typeName, type1.getResource()));
 			assertTrue(target.supportsResource(() -> typeName, type2.getResource()));
 		}
@@ -172,6 +176,12 @@
 		}
 	}
 
+	private List<IBreakpoint> getUserBreakpoints(JDIDebugTarget target) {
+		List<IBreakpoint> breakpoints = target.getBreakpoints();
+		breakpoints.remove(JavaDebugOptionsManager.getDefault().getThreadNameChangeBreakpoint());
+		return breakpoints;
+	}
+
 	static private class JDIDebugTargetProxy {
 
 		private JDIDebugTarget target;
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/JavaOutputHelpers.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/JavaOutputHelpers.java
new file mode 100644
index 0000000..30f66f6
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/JavaOutputHelpers.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.core;
+
+import org.eclipse.core.runtime.Platform;
+
+public class JavaOutputHelpers {
+
+	/**
+	 * Workaround https://bugs.openjdk.java.net/browse/JDK-8022291, which results in extra java output line like below printed to stderr of java
+	 * process on OSX.
+	 *
+	 * <pre>
+	 * objc[62928]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
+	 * </pre>
+	 */
+	public static boolean isKnownExtraneousOutput(String txt) {
+		if (!Platform.OS_MACOSX.equals(Platform.getOS())) {
+			return false;
+		}
+
+		return txt.startsWith("objc[") && txt.contains("Class JavaLaunchHelper is implemented in both");
+	}
+
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LineTrackerTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LineTrackerTests.java
index bbffc19..6f79d79 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LineTrackerTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LineTrackerTests.java
@@ -45,7 +45,7 @@
 
 	protected IJavaDebugTarget fTarget;
 
-	protected List<String> fLinesRead = new ArrayList<String>();
+	protected List<String> fLinesRead = new ArrayList<>();
 
 	protected boolean fStarted = false;
 
@@ -195,7 +195,9 @@
 		if (fStarted) {
 			try {
 				String text = fConsole.getDocument().get(line.getOffset(), line.getLength());
-				fLinesRead.add(text);
+				if (!JavaOutputHelpers.isKnownExtraneousOutput(text)) {
+					fLinesRead.add(text);
+				}
 			} catch (BadLocationException e) {
 			    e.printStackTrace();
 			}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/StratumTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/StratumTests.java
index ffe9f36..a3b5b85 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/StratumTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/StratumTests.java
@@ -10,11 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.debug.tests.core;
 
+import java.util.Arrays;
+
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
 import org.eclipse.jdt.debug.core.IJavaReferenceType;
 import org.eclipse.jdt.debug.core.IJavaStackFrame;
 import org.eclipse.jdt.debug.core.IJavaThread;
 import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.JDIHelpers;
 
 /**
  * Tests strata.
@@ -40,8 +43,10 @@
 			assertNotNull("Breakpoint not hit within timeout period", thread);
 			IJavaReferenceType type = ((IJavaStackFrame)thread.getTopStackFrame()).getReferenceType();
 			String[] strata = type.getAvailableStrata();
-			assertEquals("Wrong number of available strata", 1, strata.length);
+			Arrays.sort(strata);
+			assertEquals("Wrong number of available strata", 2, strata.length);
 			assertEquals("Wrong strata", "Java", strata[0]);
+			assertEquals("Wrong strata", JDIHelpers.STRATA_ID, strata[1]);
 		} finally {
 			terminateAndRemove(thread);
 			removeAllBreakpoints();
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/sourcelookup/JarSourceLookupTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/sourcelookup/JarSourceLookupTests.java
index ab14790..fbd275d 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/sourcelookup/JarSourceLookupTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/sourcelookup/JarSourceLookupTests.java
@@ -136,7 +136,12 @@
 		createLaunchConfiguration(fgJarProject, LAUNCHCONFIGURATIONS, A_RUN_JAR);
 		ILaunchConfiguration config = getLaunchConfiguration(fgJarProject, LAUNCHCONFIGURATIONS, A_RUN_JAR);
 		IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedSourceLookupPath(config);
-		assertEquals("There should be 2 containers returned (JRE and classpath)", 2, entries.length);
+		if (JavaRuntime.isModularConfiguration(config)) {
+			// There is no DefaultProjectClasspath entry so 2 entries inside it becomes 2 separate entries now
+			assertEquals("There should be 3 containers returned (JRE and classpath)", 3, entries.length);
+		} else {
+			assertEquals("There should be 2 containers returned (JRE and classpath)", 2, entries.length);
+		}
 		IRuntimeClasspathEntry[] resolved = JavaRuntime.resolveSourceLookupPath(entries, config);
 		ISourceContainer[] containers = JavaSourceLookupUtil.translate(resolved);
 		try {
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
new file mode 100644
index 0000000..1c2ab43
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/DebugHoverTests.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ *  Copyright (c) 2017 Andrey Loskutov and others.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.ui;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
+import org.eclipse.jdi.internal.StringReferenceImpl;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaStackFrame;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.tests.TestUtil;
+import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
+import org.eclipse.jdt.internal.debug.core.model.JDILocalVariable;
+import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue;
+import org.eclipse.jdt.internal.debug.core.model.JDIValue;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jdt.internal.debug.ui.JavaDebugHover;
+import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.test.OrderedTestSuite;
+
+import junit.framework.Test;
+
+/**
+ * Tests for debug view.
+ */
+public class DebugHoverTests extends AbstractDebugUiTests {
+
+	public static Test suite() {
+		return new OrderedTestSuite(DebugHoverTests.class);
+	}
+
+	private boolean showMonitorsOriginal;
+
+	public DebugHoverTests(String name) {
+		super(name);
+	}
+
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
+		showMonitorsOriginal = jdiUIPreferences.getBoolean(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO);
+		jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, true);
+		resetPerspective(DebugViewPerspectiveFactory.ID);
+		processUiEvents(100);
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
+		jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, showMonitorsOriginal);
+		sync(() -> getActivePage().closeAllEditors(false));
+		processUiEvents(100);
+		super.tearDown();
+	}
+
+	@Override
+	protected IJavaProject getProjectContext() {
+		return get18Project();
+	}
+
+	public void testResolveInLambda() throws Exception {
+		final String typeName = "DebugHoverTest18";
+		final String expectedMethod1 = "lambda$0";
+		final String expectedMethod2 = "lambda$1";
+		final int framesNumber1 = 6;
+		final int framesNumber2 = 9;
+		final int bpLine1 = 31;
+		final int bpLine2 = 38;
+
+		IJavaBreakpoint bp1 = createLineBreakpoint(bpLine1, "", typeName + ".java", typeName);
+		IJavaBreakpoint bp2 = createLineBreakpoint(bpLine2, "", typeName + ".java", typeName);
+		bp1.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+		bp2.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD);
+		IFile file = (IFile) bp1.getMarker().getResource();
+		assertEquals(typeName + ".java", file.getName());
+
+		IJavaThread thread = null;
+		try {
+			thread = launchToBreakpoint(typeName);
+			CompilationUnitEditor part = openEditorAndValidateStack(expectedMethod1, framesNumber1, file, thread);
+
+			JavaDebugHover hover = new JavaDebugHover();
+			hover.setEditor(part);
+
+			Map<String, Region> offsets = new LinkedHashMap<>();
+			offsets.put("arg", new Region(1041, "arg".length()));
+			offsets.put("var1", new Region(1012, "var1".length()));
+			offsets.put("var2", new Region(983, "var2".length()));
+
+			Set<Entry<String, Region>> entrySet = offsets.entrySet();
+			int startLine = bpLine1;
+			int valueIndex = 0;
+			for (Entry<String, Region> varData : entrySet) {
+				// select variables and validate the hover, going backwards from the breakpoint
+				validateLine(startLine--, valueIndex++, part, hover, varData);
+			}
+
+			resumeToLineBreakpoint(thread, (ILineBreakpoint) bp2);
+			part = openEditorAndValidateStack(expectedMethod2, framesNumber2, file, thread);
+
+			offsets = new LinkedHashMap<>();
+			offsets.put("arg", new Region(1198, "arg".length()));
+			offsets.put("var1", new Region(1168, "var1".length()));
+			offsets.put("var3", new Region(1138, "var3".length()));
+			// This will not work yet, I have no idea how to identify parent
+			// lambda element...
+			// offsets.put("var2", new Region(1108, "var2".length()));
+
+			entrySet = offsets.entrySet();
+			startLine = bpLine2;
+			valueIndex = 0;
+			for (Entry<String, Region> varData : entrySet) {
+				// select variables and validate the hover, going backwards from the breakpoint
+				validateLine(startLine--, valueIndex++, part, hover, varData);
+			}
+		}
+		finally {
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}
+	}
+
+	private CompilationUnitEditor openEditorAndValidateStack(final String expectedMethod, final int expectedFramesNumber, IFile file, IJavaThread thread) throws Exception, DebugException {
+		// Let now all pending jobs proceed, ignore console jobs
+		sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class));
+		CompilationUnitEditor part = (CompilationUnitEditor) sync(() -> openEditor(file));
+		processUiEvents(100);
+
+		// Prepare breakpoint and check everything below UI is OK
+		IBreakpoint hit = getBreakpoint(thread);
+		assertNotNull("Suspended, but not by breakpoint", hit);
+
+		IJavaStackFrame topFrame = (IJavaStackFrame) thread.getTopStackFrame();
+		assertNotNull("There should be a stackframe", topFrame);
+		assertEquals(expectedMethod, topFrame.getMethodName());
+
+		IStackFrame[] frames = topFrame.getThread().getStackFrames();
+		assertEquals(expectedFramesNumber, frames.length);
+		return part;
+	}
+
+	private void validateLine(final int line, int valueIndex, CompilationUnitEditor part, JavaDebugHover hover, Entry<String, Region> varData) throws Exception, DebugException {
+		String variableName = varData.getKey();
+		IRegion region = varData.getValue();
+		String text = selectAndReveal(part, line, region);
+		assertEquals(variableName, text);
+		Object args = sync(() -> hover.getHoverInfo2(part.getViewer(), region));
+
+		assertNotNull(args);
+		JDILocalVariable var = (JDILocalVariable) args;
+		assertEquals(variableName, var.getName());
+		JDIValue value = (JDIValue) var.getValue();
+		assertEquals(JDIObjectValue.class, value.getClass());
+		JDIObjectValue valueObj = (JDIObjectValue) var.getValue();
+		StringReferenceImpl object = (StringReferenceImpl) valueObj.getUnderlyingObject();
+		assertEquals("v" + valueIndex, object.value());
+	}
+
+	String selectAndReveal(CompilationUnitEditor editor, int line, IRegion region) throws Exception {
+		ITextSelection selection = sync(() -> {
+			getActivePage().activate(editor);
+			editor.selectAndReveal(region.getOffset(), region.getLength());
+			processUiEvents(100);
+			return (ITextSelection) editor.getSelectionProvider().getSelection();
+		});
+		int actualLine = sync(() -> selection.getStartLine() + 1);
+		assertEquals(line, actualLine);
+		return sync(() -> selection.getText());
+	}
+
+}
diff --git a/org.eclipse.jdt.debug.ui/.settings/.api_filters b/org.eclipse.jdt.debug.ui/.settings/.api_filters
index 4f59252..8e822e4 100644
--- a/org.eclipse.jdt.debug.ui/.settings/.api_filters
+++ b/org.eclipse.jdt.debug.ui/.settings/.api_filters
@@ -1,5 +1,19 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.jdt.debug.ui" version="2">
+    <resource path="META-INF/MANIFEST.MF">
+        <filter comment="API was backported to 4.7.1a" id="926941240">
+            <message_arguments>
+                <message_argument value="3.9.0"/>
+                <message_argument value="3.8.50"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Photon changes" id="926941240">
+            <message_arguments>
+                <message_argument value="3.9.0"/>
+                <message_argument value="3.8.51"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaClasspathTab.java" type="org.eclipse.jdt.debug.ui.launchConfigurations.JavaClasspathTab">
         <filter comment="Known illegal extension" id="576720909">
             <message_arguments>
@@ -8,15 +22,6 @@
             </message_arguments>
         </filter>
     </resource>
-    <resource path="ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaDependenciesTab.java" type="org.eclipse.jdt.debug.ui.launchConfigurations.JavaDependenciesTab">
-        <filter id="1108344834">
-            <message_arguments>
-                <message_argument value="3.9"/>
-                <message_argument value="3.8"/>
-                <message_argument value="org.eclipse.jdt.debug.ui.launchConfigurations.JavaDependenciesTab"/>
-            </message_arguments>
-        </filter>
-    </resource>
     <resource path="ui/org/eclipse/jdt/internal/debug/ui/classpath/ClasspathEntry.java" type="org.eclipse.jdt.internal.debug.ui.classpath.ClasspathEntry">
         <filter comment="Known illegal implementation" id="574619656">
             <message_arguments>
diff --git a/org.eclipse.jdt.debug.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.debug.ui/.settings/org.eclipse.jdt.core.prefs
index 4503553..15f7da9 100644
--- a/org.eclipse.jdt.debug.ui/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jdt.debug.ui/.settings/org.eclipse.jdt.core.prefs
@@ -220,10 +220,10 @@
 org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert

diff --git a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
index 03f1d11..0b2dc66 100644
--- a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.debug.ui; singleton:=true
-Bundle-Version: 3.8.52.qualifier
+Bundle-Version: 3.9.0.qualifier
 Bundle-Activator: org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -37,8 +37,8 @@
  org.eclipse.core.filebuffers;bundle-version="[3.5.0,4.0.0)",
  org.eclipse.core.variables;bundle-version="[3.2.0,4.0.0)",
  org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.jdt.core;bundle-version="[3.8.0,4.0.0)",
- org.eclipse.debug.ui;bundle-version="[3.10.0,4.0.0)",
+ org.eclipse.jdt.core;bundle-version="[3.14.0,4.0.0)",
+ org.eclipse.debug.ui;bundle-version="[3.13.0,4.0.0)",
  org.eclipse.jdt.debug;bundle-version="[3.10.0,4.0.0)",
  org.eclipse.jdt.launching;bundle-version="[3.7.0,4.0.0)",
  org.eclipse.jdt.ui;bundle-version="[3.8.0,4.0.0)",
@@ -53,3 +53,4 @@
  org.eclipse.debug.core;bundle-version="[3.9.0,4.0.0)"
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: org.eclipse.jdt.debug.ui
diff --git a/org.eclipse.jdt.debug.ui/forceQualifierUpdate.txt b/org.eclipse.jdt.debug.ui/forceQualifierUpdate.txt
new file mode 100644
index 0000000..3e80b00
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/forceQualifierUpdate.txt
@@ -0,0 +1,3 @@
+# To force a version qualifier update, add the bug here
+Bug 522092 - Comparator errors from I20170909-0920
+Bug 530709 - Comparator errors in jdt debug and jdt ui in I20180204-2000
diff --git a/org.eclipse.jdt.debug.ui/plugin.properties b/org.eclipse.jdt.debug.ui/plugin.properties
index c454609..abe533a 100644
--- a/org.eclipse.jdt.debug.ui/plugin.properties
+++ b/org.eclipse.jdt.debug.ui/plugin.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2017 IBM Corporation and others.
+# Copyright (c) 2000, 2018 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -44,7 +44,7 @@
 
 ForceReturn.label=&Force Return
 
-displayViewName=Display
+displayViewName=Debug Shell
 
 filteringPage.label=Filtering
 commonPage.label=Common
@@ -284,7 +284,7 @@
 allReferencesInView.label=Show &References
 allReferencesInView.tooltip=Shows references to each object in the variables view as an array of objects.
 
-preferenceKeywords.general=java debug suspend hot hcr timeout breakpoints code execution exceptions conditional evaluations
+preferenceKeywords.general=java debug suspend hot hcr timeout breakpoints code execution exceptions conditional evaluations source lookup
 preferenceKeywords.jres= debug java jdk 1.5 5.0 1.4 1.6 6.0 1.7 7.0 jres vms javadoc libraries source attachment
 preferenceKeywords.detailFormatters= debug java details toString variables pane
 preferenceKeywords.logicalStructures=debug java logical structures variables details pane
diff --git a/org.eclipse.jdt.debug.ui/plugin.xml b/org.eclipse.jdt.debug.ui/plugin.xml
index ee5c856..518f024 100644
--- a/org.eclipse.jdt.debug.ui/plugin.xml
+++ b/org.eclipse.jdt.debug.ui/plugin.xml
@@ -550,7 +550,7 @@
             targetID="org.eclipse.debug.ui.DebugPerspective">
          <view
                relative="org.eclipse.ui.console.ConsoleView"
-               visible="false"
+               visible="true"
                relationship="stack"
                id="org.eclipse.jdt.debug.ui.DisplayView">
          </view>
@@ -570,7 +570,7 @@
                relative="org.eclipse.ui.console.ConsoleView"
                visible="false"
                relationship="stack"
-               id="org.eclipse.search.SearchResultView">
+               id="org.eclipse.search.ui.views.SearchView">
          </view>
          <viewShortcut
                id="org.eclipse.jdt.debug.ui.DisplayView">
@@ -3606,6 +3606,10 @@
           class="org.eclipse.jdt.internal.debug.ui.breakpoints.SuspendOnUncaughtExceptionListener"
           id="org.eclipse.jdt.debug.ui.uncaughtExceptionListener">
     </breakpointListener>
+    <breakpointListener
+          class="org.eclipse.jdt.internal.debug.ui.breakpoints.ThreadNameChangeListener"
+          id="org.eclipse.jdt.debug.ui.threadNameChangeListener">
+    </breakpointListener>
  </extension>
  <extension
        point="org.eclipse.debug.ui.detailPaneFactories">
@@ -3682,7 +3686,4 @@
        </enabledWhen>
     </handler>
  </extension>
-  
-   
- 
 </plugin>
diff --git a/org.eclipse.jdt.debug.ui/pom.xml b/org.eclipse.jdt.debug.ui/pom.xml
index 5139968..eedde7e 100644
--- a/org.eclipse.jdt.debug.ui/pom.xml
+++ b/org.eclipse.jdt.debug.ui/pom.xml
@@ -14,11 +14,11 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.3-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.debug.ui</artifactId>
-  <version>3.8.52-SNAPSHOT</version>
+  <version>3.9.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
   <properties>
     <code.ignoredWarnings>-warn:+resource,-deprecation,unavoidableGenericProblems</code.ignoredWarnings>
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaApplicationLaunchShortcut.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaApplicationLaunchShortcut.java
index 9ac5acd..f3274b5 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaApplicationLaunchShortcut.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaApplicationLaunchShortcut.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2015 IBM Corporation and others.
+ * Copyright (c) 2007, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -25,9 +25,12 @@
 import org.eclipse.debug.core.ILaunchConfigurationType;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
 import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IMember;
 import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
@@ -47,12 +50,32 @@
  * @since 3.3
  */
 public class JavaApplicationLaunchShortcut extends JavaLaunchShortcut {
+	/**
+	 * Test if a type is from a location marked as test code (from the perspective of the project where it is defined.)
+	 *
+	 * @param type
+	 *            the type that is examined
+	 * @return false, if the corresponding class path entry is found and is not marked as test, otherwise true
+	 * @throws JavaModelException
+	 *             when access to the classpath entry corresponding to the given type fails.
+	 */
+	private static boolean isTestCode(IType type) throws JavaModelException {
+		IPackageFragmentRoot packageFragmentRoot = (IPackageFragmentRoot) type.getPackageFragment().getParent();
+		IJavaProject javaProject = packageFragmentRoot.getJavaProject();
+		if (javaProject != null) {
+			IClasspathEntry entry = javaProject.getClasspathEntryFor(packageFragmentRoot.getPath());
+			if (entry != null && !entry.isTest()) {
+				return false;
+			}
+		}
+		return true;
+	}
 
 	/**
-	 * Returns the Java elements corresponding to the given objects. Members are translated
-	 * to corresponding declaring types where possible.
+	 * Returns the Java elements corresponding to the given objects. Members are translated to corresponding declaring types where possible.
 	 *
-	 * @param objects selected objects
+	 * @param objects
+	 *            selected objects
 	 * @return corresponding Java elements
 	 * @since 3.5
 	 */
@@ -89,6 +112,9 @@
 			wc = configType.newInstance(null, getLaunchManager().generateLaunchConfigurationName(type.getTypeQualifiedName('.')));
 			wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, type.getFullyQualifiedName());
 			wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, type.getJavaProject().getElementName());
+			if (!isTestCode(type)) {
+				wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, true);
+			}
 			wc.setMappedResources(new IResource[] {type.getUnderlyingResource()});
 			config = wc.doSave();
 		} catch (CoreException exception) {
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaArgumentsTab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaArgumentsTab.java
index bf2eced..d72b082 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaArgumentsTab.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaArgumentsTab.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2015 IBM Corporation and others.
+ *  Copyright (c) 2000, 2017 IBM Corporation and others.
  *  All rights reserved. This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License v1.0
  *  which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
  *     Remy Chi Jian Suen <remy.suen@gmail.com>
  *      - Bug 214696 Expose WorkingDirectoryBlock as API
  *      - Bug 221973 Make WorkingDirectoryBlock from JDT a Debug API class
+ *      Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 package org.eclipse.jdt.debug.ui.launchConfigurations;
 
@@ -70,6 +71,7 @@
 	protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
 
 	public JavaArgumentsTab() {
+		super();
 		fVMArgumentsBlock = createVMArgsBlock();
 		fWorkingDirectoryBlock = createWorkingDirBlock();
 	}
@@ -318,5 +320,19 @@
 	public void deactivated(ILaunchConfigurationWorkingCopy workingCopy) {
 		// do nothing when deactivated
 	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jdt.debug.ui.launchConfigurations.JavaLaunchTab#initializeAttributes()
+	 * @since 3.9
+	 */
+	@Override
+	protected void initializeAttributes() {
+		super.initializeAttributes();
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, LauncherMessages.JavaArgumentsTab_AttributeLabel_ProgramArguments);
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, LauncherMessages.JavaArgumentsTab_AttributeLabel_VMArguments);
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_USE_START_ON_FIRST_THREAD, LauncherMessages.JavaArgumentsTab_AttributeLabel_UseAtStart);
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, LauncherMessages.JavaArgumentsTab_AttributeLabel_WorkingDirectory);
+	}
 }
 
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaClasspathTab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaClasspathTab.java
index 0b57588..ff7f8f5 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaClasspathTab.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaClasspathTab.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     BEA - Daniel R Somerfield - Bug 88939
+ *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 package org.eclipse.jdt.debug.ui.launchConfigurations;
 
@@ -23,6 +24,7 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.internal.ui.SWTFactory;
 import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds;
 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
 import org.eclipse.jdt.internal.debug.ui.JavaDebugImages;
@@ -56,6 +58,8 @@
 import org.eclipse.jface.action.IAction;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.GridData;
@@ -91,10 +95,13 @@
 	 */
 	protected ILaunchConfiguration fLaunchConfiguration;
 
+	private Button fExcludeTestCodeButton;
+
 	/**
 	 * Constructor
 	 */
 	public JavaClasspathTab() {
+		super();
 		setHelpContextId(IJavaDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_CLASSPATH_TAB);
 	}
 
@@ -138,6 +145,16 @@
 		pathButtonComp.setFont(font);
 
 		createPathButtons(pathButtonComp);
+		SWTFactory.createVerticalSpacer(comp, 2);
+
+		fExcludeTestCodeButton = SWTFactory.createCheckButton(comp, LauncherMessages.JavaClasspathTab_Exclude_Test_Code, null, false, 2);
+		fExcludeTestCodeButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent evt) {
+				setDirty(true);
+				updateLaunchConfigurationDialog();
+			}
+		});
 	}
 
 	/**
@@ -209,6 +226,10 @@
 	public void initializeFrom(ILaunchConfiguration configuration) {
 		refresh(configuration);
 		fClasspathViewer.getTreeViewer().expandToLevel(2);
+		try {
+			fExcludeTestCodeButton.setSelection(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false));
+		} catch (CoreException e) {
+		}
 	}
 
 	/* (non-Javadoc)
@@ -290,6 +311,16 @@
 					JDIDebugUIPlugin.statusDialog(LauncherMessages.JavaClasspathTab_Unable_to_save_classpath_1, e.getStatus());
 				}
 			}
+			try {
+				boolean previousExcludeTestCode = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false);
+				if (previousExcludeTestCode != fExcludeTestCodeButton.getSelection()) {
+					configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, fExcludeTestCodeButton.getSelection());
+					fClasspathViewer.setEntries(JavaRuntime.computeUnresolvedRuntimeClasspath(configuration));
+				}
+			}
+			catch (CoreException e) {
+				JDIDebugUIPlugin.statusDialog(LauncherMessages.JavaClasspathTab_Unable_to_save_classpath_1, e.getStatus());
+			}
 		}
 	}
 
@@ -498,4 +529,16 @@
 	protected ClasspathModel getModel() {
 		return fModel;
 	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jdt.debug.ui.launchConfigurations.JavaLaunchTab#initializeAttributes()
+	 * @since 3.9
+	 */
+	@Override
+	protected void initializeAttributes() {
+		super.initializeAttributes();
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, LauncherMessages.JavaClasspathTab_AttributeLabel_DefaultClasspath);
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, LauncherMessages.JavaClasspathTab_AttributeLabel_Classpath);
+	}
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaDependenciesTab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaDependenciesTab.java
index 35629ff..0cf229f 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaDependenciesTab.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaDependenciesTab.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2017 IBM Corporation and others.
+ * Copyright (c) 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.internal.ui.SWTFactory;
 import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds;
 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
 import org.eclipse.jdt.internal.debug.ui.JavaDebugImages;
@@ -34,9 +35,9 @@
 import org.eclipse.jdt.internal.debug.ui.actions.AddProjectAction;
 import org.eclipse.jdt.internal.debug.ui.actions.AddVariableAction;
 import org.eclipse.jdt.internal.debug.ui.actions.AttachSourceAction;
-import org.eclipse.jdt.internal.debug.ui.actions.EditClasspathEntryAction;
 import org.eclipse.jdt.internal.debug.ui.actions.MoveDownAction;
 import org.eclipse.jdt.internal.debug.ui.actions.MoveUpAction;
+import org.eclipse.jdt.internal.debug.ui.actions.OverrideDependenciesAction;
 import org.eclipse.jdt.internal.debug.ui.actions.RemoveAction;
 import org.eclipse.jdt.internal.debug.ui.actions.RestoreDefaultEntriesAction;
 import org.eclipse.jdt.internal.debug.ui.actions.RuntimeClasspathAction;
@@ -55,6 +56,8 @@
 import org.eclipse.jface.action.IAction;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.GridData;
@@ -88,6 +91,8 @@
 	 */
 	protected ILaunchConfiguration fLaunchConfiguration;
 
+	private Button fExcludeTestCodeButton;
+
 	/**
 	 * Constructor
 	 */
@@ -135,6 +140,17 @@
 		pathButtonComp.setFont(font);
 
 		createPathButtons(pathButtonComp);
+
+		SWTFactory.createVerticalSpacer(comp, 2);
+
+		fExcludeTestCodeButton = SWTFactory.createCheckButton(comp, LauncherMessages.JavaClasspathTab_Exclude_Test_Code, null, false, 2);
+		fExcludeTestCodeButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent evt) {
+				setDirty(true);
+				updateLaunchConfigurationDialog();
+			}
+		});
 	}
 
 	/**
@@ -172,12 +188,14 @@
 		IAction[] adv = advancedActions.toArray(new IAction[advancedActions.size()]);
 		createButton(pathButtonComp, new AddAdvancedAction(fClasspathViewer, adv));
 
-		action = new EditClasspathEntryAction(fClasspathViewer, getLaunchConfiguration());
+		action = new OverrideDependenciesAction(fClasspathViewer, this);
 		createButton(pathButtonComp, action);
+		action.setEnabled(true);
 
 		action= new RestoreDefaultEntriesAction(fClasspathViewer, this);
 		createButton(pathButtonComp, action);
 		action.setEnabled(true);
+
 	}
 
 	/**
@@ -208,6 +226,10 @@
 	public void initializeFrom(ILaunchConfiguration configuration) {
 		refresh(configuration);
 		fClasspathViewer.getTreeViewer().expandToLevel(2);
+		try {
+			fExcludeTestCodeButton.setSelection(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false));
+		} catch (CoreException e) {
+		}
 	}
 
 	/* (non-Javadoc)
@@ -299,6 +321,16 @@
 					JDIDebugUIPlugin.statusDialog(LauncherMessages.JavaClasspathTab_Unable_to_save_classpath_1, e.getStatus());
 				}
 			}
+			try {
+				boolean previousExcludeTestCode = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false);
+				if (previousExcludeTestCode != fExcludeTestCodeButton.getSelection()) {
+					configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, fExcludeTestCodeButton.getSelection());
+					fClasspathViewer.setEntries(JavaRuntime.computeUnresolvedRuntimeClasspath(configuration));
+				}
+			}
+			catch (CoreException e) {
+				JDIDebugUIPlugin.statusDialog(LauncherMessages.JavaClasspathTab_Unable_to_save_classpath_1, e.getStatus());
+			}
 		}
 	}
 
@@ -359,6 +391,19 @@
 			ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy();
 			wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, true);
 			IRuntimeClasspathEntry[] entries= JavaRuntime.computeUnresolvedRuntimeClasspath(wc);
+			ArrayList<IRuntimeClasspathEntry> grouped = new ArrayList<>(entries.length);
+			// move all modulepath entries to the front, like in the ui
+			for (IRuntimeClasspathEntry entry : entries) {
+				if (entry.getClasspathProperty() == IRuntimeClasspathEntry.MODULE_PATH) {
+					grouped.add(entry);
+				}
+			}
+			for (IRuntimeClasspathEntry entry : entries) {
+				if (entry.getClasspathProperty() != IRuntimeClasspathEntry.MODULE_PATH) {
+					grouped.add(entry);
+				}
+			}
+			entries = grouped.toArray(new IRuntimeClasspathEntry[grouped.size()]);
 			if (classpath.length == entries.length) {
 				for (int i = 0; i < entries.length; i++) {
 					IRuntimeClasspathEntry entry = entries[i];
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaJRETab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaJRETab.java
index 5afaf2e..33f200f 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaJRETab.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaJRETab.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 package org.eclipse.jdt.debug.ui.launchConfigurations;
 
@@ -96,13 +97,31 @@
 		}
 	};
 
+	private boolean fCheckForClasspathDependenciesChange;
+
 	/**
 	 * Constructor
 	 */
 	public JavaJRETab() {
+		super();
 		setHelpContextId(IJavaDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_JRE_TAB);
 	}
 
+	/**
+	 * Constructor
+	 *
+	 * @param checkForClasspathDependenciesChange
+	 *            if this is true, and the user changes between a non-modular jvm and a modular jvm, the user will be asked to apply changes before
+	 *            the tab is exited and the tabs will be refreshed.
+	 *
+	 * @since 3.9
+	 */
+	public JavaJRETab(boolean checkForClasspathDependenciesChange) {
+		this();
+		this.fCheckForClasspathDependenciesChange = checkForClasspathDependenciesChange;
+	}
+
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#dispose()
 	 */
@@ -643,9 +662,11 @@
 	 */
 	@Override
 	public boolean OkToLeaveTab() {
-		boolean newJREModular = JavaRuntime.isModularConfiguration(getLaunchConfiguration());
-		if (fCurrentJREModular != newJREModular) {
-			return handleClasspathDependenciesChange(newJREModular);
+		if (fCheckForClasspathDependenciesChange) {
+			boolean newJREModular = JavaRuntime.isModularConfiguration(getLaunchConfiguration());
+			if (fCurrentJREModular != newJREModular) {
+				return handleClasspathDependenciesChange(newJREModular);
+			}
 		}
 
 		return true;
@@ -674,4 +695,16 @@
 		}
 		return false;
 	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jdt.debug.ui.launchConfigurations.JavaLaunchTab#initializeAttributes()
+	 * @since 3.9
+	 */
+	@Override
+	protected void initializeAttributes() {
+		super.initializeAttributes();
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, LauncherMessages.JavaJRETab_AttributeLabel_JREContainerPath);
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, LauncherMessages.JavaJRETab_AttributeLabel_VMAttributes);
+	}
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchShortcut.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchShortcut.java
index 61d7bea..0897a9d 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchShortcut.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchShortcut.java
@@ -113,7 +113,12 @@
 		}
 		catch (InterruptedException e) {return;}
 		catch (CoreException e) {
-			MessageDialog.openError(getShell(), LauncherMessages.JavaLaunchShortcut_0, e.getMessage());
+			JDIDebugUIPlugin.log(e);
+			String message = e.getMessage();
+			if (message == null || message.isEmpty()) {
+				message = LauncherMessages.JavaLaunchShortcut_1;
+			}
+			MessageDialog.openError(getShell(), LauncherMessages.JavaLaunchShortcut_0, message);
 			return;
 		}
 		IType type = null;
@@ -258,9 +263,6 @@
 		return JDIDebugUIPlugin.getActiveWorkbenchShell();
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.ui.IEditorPart, java.lang.String)
-	 */
 	@Override
 	public void launch(IEditorPart editor, String mode) {
 		IEditorInput input = editor.getEditorInput();
@@ -270,9 +272,6 @@
 		}
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.jface.viewers.ISelection, java.lang.String)
-	 */
 	@Override
 	public void launch(ISelection selection, String mode) {
 		if (selection instanceof IStructuredSelection) {
@@ -280,17 +279,11 @@
 		}
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchableResource(org.eclipse.ui.IEditorPart)
-	 */
 	@Override
 	public IResource getLaunchableResource(IEditorPart editorpart) {
 		return getLaunchableResource(editorpart.getEditorInput());
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchableResource(org.eclipse.jface.viewers.ISelection)
-	 */
 	@Override
 	public IResource getLaunchableResource(ISelection selection) {
 		if (selection instanceof IStructuredSelection) {
@@ -320,18 +313,12 @@
 		return null;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchConfigurations(org.eclipse.ui.IEditorPart)
-	 */
 	@Override
 	public ILaunchConfiguration[] getLaunchConfigurations(IEditorPart editorpart) {
 		// let the framework resolve configurations based on resource mapping
 		return null;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchConfigurations(org.eclipse.jface.viewers.ISelection)
-	 */
 	@Override
 	public ILaunchConfiguration[] getLaunchConfigurations(ISelection selection) {
 		// let the framework resolve configurations based on resource mapping
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchTab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchTab.java
index 7376eaa..7f239dd 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchTab.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaLaunchTab.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 package org.eclipse.jdt.debug.ui.launchConfigurations;
 
@@ -20,6 +21,7 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jdt.internal.debug.ui.launcher.LauncherMessages;
 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredSelection;
@@ -123,5 +125,14 @@
 		setCurrentLaunchConfiguration(config);
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#initializeAttributes()
+	 * @since 3.9
+	 */
+	@Override
+	protected void initializeAttributes() {
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, LauncherMessages.JavaLauncherTab_AttributeLabel_ProjectName);
+	}
 }
 
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java
index 505b6d4..6360a51 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/launchConfigurations/JavaMainTab.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 IBM Corporation and others.
+ * Copyright (c) 2005, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 package org.eclipse.jdt.debug.ui.launchConfigurations;
 
@@ -228,6 +229,9 @@
 				setErrorMessage(NLS.bind(LauncherMessages.JavaMainTab_19, new String[]{status.getMessage()}));
 				return false;
 			}
+		} else {
+			setErrorMessage(LauncherMessages.JavaMainTab_missing_project);
+			return false;
 		}
 		name = fMainText.getText().trim();
 		if (name.length() == 0) {
@@ -286,6 +290,20 @@
 		initializeMainTypeAndName(javaElement, config);
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.debug.ui.launcher.SharedJavaMainTab#initializeAttributes()
+	 * @since 3.9
+	 */
+	@Override
+	protected void initializeAttributes() {
+		super.initializeAttributes();
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, LauncherMessages.SharedJavaMainTab_AttributeLabel_MainTypeName);
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, LauncherMessages.JavaMainTab_AttributeLabel_StopInMain);
+		getAttributesLabelsForPrototype().put(JavaMainTab.ATTR_INCLUDE_EXTERNAL_JARS, LauncherMessages.JavaMainTab_AttributeLabel_IncludeExternalJars);
+		getAttributesLabelsForPrototype().put(JavaMainTab.ATTR_CONSIDER_INHERITED_MAIN, LauncherMessages.JavaMainTab_AttributeLabel_InheritedMain);
+	}
+
 	/**
 	 * updates the external jars attribute from the specified launch config
 	 * @param config the config to load from
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
index d468df6..d2632d3 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
@@ -71,6 +71,9 @@
 	public static String JavaDebugPreferencePage_0;
 	public static String JavaDebugPreferencePage_20;
 
+	public static String JavaDebugPreferencePage_advancedSourcelookup;
+	public static String JavaDebugPreferencePage_listenToThreadNameChanges;
+
 	public static String JavaDebugPreferencePage_only_include_exported_entries;
 	public static String JavaDebugPreferencePage_filterUnrelatedBreakpoints;
 	public static String JavaDebugPreferencePage_promptWhenDeletingCondidtionalBreakpoint;
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
index 9e68739..7e8604e 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2016 IBM Corporation and others.
+# Copyright (c) 2000, 2018 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -300,6 +300,8 @@
 JavaDebugPreferencePage_27=Modification
 JavaDebugPreferencePage_promptWhenDeletingCondidtionalBreakpoint=&Prompt for confirmation when deleting a conditional breakpoint from editor
 JavaDebugPreferencePage_0=See <a>''{0}''</a> for general debug settings.
+JavaDebugPreferencePage_advancedSourcelookup=Use &advanced source lookup (JRE 1.5 and higher)  
+JavaDebugPreferencePage_listenToThreadNameChanges=L&isten to thread name changes
 JavaDebugPreferencePage_only_include_exported_entries=Onl&y include exported classpath entries when launching
 JavaDebugPreferencePage_filterUnrelatedBreakpoints=Do &not install breakpoints from unrelated projects
 JavaVariableLabelProvider_0=unavailable
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java
index 42fa337..a6bba15 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ExpressionInformationControlCreator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2015 IBM Corporation and others.
+ * Copyright (c) 2008, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,6 +26,10 @@
 import org.eclipse.debug.ui.AbstractDebugView;
 import org.eclipse.debug.ui.IDebugUIConstants;
 import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.preference.JFacePreferences;
+import org.eclipse.jface.resource.ColorRegistry;
+import org.eclipse.jface.resource.JFaceColors;
+import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.jface.text.AbstractInformationControl;
 import org.eclipse.jface.text.IInformationControl;
 import org.eclipse.jface.text.IInformationControlCreator;
@@ -44,6 +48,7 @@
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Layout;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Tree;
@@ -173,8 +178,8 @@
 			@Override
 			public void paneChanged(String newPaneID) {
 				if (newPaneID.equals(DefaultDetailPane.ID)){
-					fDetailPane.getCurrentControl().setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
-					fDetailPane.getCurrentControl().setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+					fDetailPane.getCurrentControl().setForeground(getSystemForegroundColor());
+					fDetailPane.getCurrentControl().setBackground(getSystemBackgroundColor());
 				}
 			}
 
@@ -359,8 +364,8 @@
 				}
 			});
 
-	        setForegroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
-	        setBackgroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+	        setForegroundColor(getSystemForegroundColor());
+	        setBackgroundColor(getSystemBackgroundColor());
 		}
 
 
@@ -475,5 +480,26 @@
 		return new ExpressionInformationControl(parent, false);
 	}
 
+	private static Color getSystemForegroundColor() {
+		ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
+		Color foreground = colorRegistry.get(JFacePreferences.INFORMATION_FOREGROUND_COLOR);
+
+		if (foreground == null) {
+			return JFaceColors.getInformationViewerForegroundColor(Display.getDefault());
+		}
+
+		return foreground;
+	}
+
+	private static Color getSystemBackgroundColor() {
+		ColorRegistry colorRegistry = JFaceResources.getColorRegistry();
+		Color background = colorRegistry.get(JFacePreferences.INFORMATION_BACKGROUND_COLOR);
+
+		if (background == null) {
+			return JFaceColors.getInformationViewerBackgroundColor(Display.getDefault());
+		}
+
+		return background;
+	}
 
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java
index 07b52ef..e95a611 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/IJDIPreferencesConstants.java
@@ -30,7 +30,12 @@
 	 * execution when a compilation error is encountered
 	 * (while debugging).
 	 */
-	public static final String PREF_SUSPEND_ON_COMPILATION_ERRORS= IJavaDebugUIConstants.PLUGIN_ID + ".suspend_on_compilation_errors"; //$NON-NLS-1$
+	public static final String PREF_SUSPEND_ON_COMPILATION_ERRORS = IJavaDebugUIConstants.PLUGIN_ID + ".suspend_on_compilation_errors"; //$NON-NLS-1$
+
+	/**
+	 * Boolean preference controlling whether to listen to thread name changes (while debugging).
+	 */
+	public static final String PREF_LISTEN_ON_THREAD_NAME_CHANGES = IJavaDebugUIConstants.PLUGIN_ID + ".javaDebug.ListenOnThreadNameChanges"; //$NON-NLS-1$
 
 	/**
 	 * Boolean preference controlling whether synthetic
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPlugin.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPlugin.java
index 36d112b..3a6ac7e 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPlugin.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPlugin.java
@@ -193,12 +193,14 @@
 	}
 
 	/**
-	 * Logs an internal error with the specified message.
+	 * Logs an internal error with the specified message and throwable
 	 *
 	 * @param message the error message to log
+	 * @param e
+	 *            the exception to be logged
 	 */
-	public static void logErrorMessage(String message) {
-		log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, message, null));
+	public static void log(String message, Throwable e) {
+		log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, message, e));
 	}
 
 	/**
@@ -207,7 +209,7 @@
 	 * @param e the exception to be logged
 	 */
 	public static void log(Throwable e) {
-		log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "Internal Error", e));   //$NON-NLS-1$
+		log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "Internal Error", e)); //$NON-NLS-1$
 	}
 
 	/**
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java
index 4d279fd..4246f0f 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIDebugUIPreferenceInitializer.java
@@ -24,16 +24,12 @@
 		super();
 	}
 
-	/*
-	 * (non-Javadoc)
-	 *
-	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
-	 */
 	@Override
 	public void initializeDefaultPreferences() {
 		IPreferenceStore store = JDIDebugUIPlugin.getDefault().getPreferenceStore();
 		store.setDefault(IJDIPreferencesConstants.PREF_SUSPEND_ON_COMPILATION_ERRORS, true);
 		store.setDefault(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, true);
+		store.setDefault(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES, true);
 		store.setDefault(IJDIPreferencesConstants.PREF_ALERT_HCR_FAILED, true);
 		store.setDefault(IJDIPreferencesConstants.PREF_ALERT_HCR_NOT_SUPPORTED, true);
 		store.setDefault(IJDIPreferencesConstants.PREF_ALERT_OBSOLETE_METHODS, true);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
index 627e301..236d726 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugHover.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -136,7 +136,7 @@
 	 *
 	 * @return local variable or <code>null</code>
 	 */
-	private IVariable findLocalVariable(IJavaStackFrame frame, String variableName) {
+	public static IVariable findLocalVariable(IJavaStackFrame frame, String variableName) {
 		if (frame != null) {
 			try {
 				return frame.findVariable(variableName);
@@ -391,8 +391,13 @@
             				boolean equal = false;
             				if (method.isBinary()) {
             					// compare resolved signatures
-            					if (method.getSignature().equals(frame.getSignature())) {
+								if (method.getSignature().equals(frame.getSignature()) && method.getElementName().equals(frame.getMethodName())) {
             						equal = true;
+								} else {
+									// Check if there are variables captured by lambda, see bug 516278
+									if (LambdaUtils.isLambdaFrame(frame)) {
+										return LambdaUtils.findLocalVariableFromLambdaScope(frame, var);
+									}
             					}
             				} else {
             					// compare unresolved signatures
@@ -420,6 +425,11 @@
 										}
 										catch (NumberFormatException ex) {
 										}
+									} else {
+										// Check if there are variables captured by lambda, see bug 516278
+										if (LambdaUtils.isLambdaFrame(frame)) {
+											return LambdaUtils.findLocalVariableFromLambdaScope(frame, var);
+										}
 									}
 								}
             				}
@@ -438,9 +448,6 @@
 	    return null;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.jface.text.ITextHoverExtension2#getInformationPresenterControlCreator()
-	 */
 	public IInformationControlCreator getInformationPresenterControlCreator() {
 		return new ExpressionInformationControlCreator();
 	}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugOptionsManager.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugOptionsManager.java
index 6afe57d..d229f28 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugOptionsManager.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugOptionsManager.java
@@ -62,6 +62,7 @@
 import org.eclipse.jdt.internal.debug.ui.actions.JavaBreakpointPropertiesAction;

 import org.eclipse.jdt.internal.debug.ui.breakpoints.SuspendOnCompilationErrorListener;

 import org.eclipse.jdt.internal.debug.ui.breakpoints.SuspendOnUncaughtExceptionListener;

+import org.eclipse.jdt.internal.debug.ui.breakpoints.ThreadNameChangeListener;

 import org.eclipse.jdt.internal.debug.ui.snippeteditor.ScrapbookLauncher;

 import org.eclipse.jface.preference.IPreferenceStore;

 import org.eclipse.jface.util.IPropertyChangeListener;

@@ -104,6 +105,11 @@
 	private IJavaExceptionBreakpoint fSuspendOnErrorBreakpoint = null;

 

 	/**

+	 * Breakpoint used to listen on thread name changes

+	 */

+	private IJavaMethodEntryBreakpoint fThreadNameChangeBreakpoint;

+

+	/**

 	 * A label provider

 	 */

 	private static ILabelProvider fLabelProvider= DebugUITools.newDebugModelPresentation();

@@ -170,6 +176,18 @@
 				status.add(e.getStatus());

 			}

 

+			// thread name change breakpoint

+			try {

+				IJavaMethodEntryBreakpoint bp = JDIDebugModel.createMethodEntryBreakpoint(ResourcesPlugin.getWorkspace().getRoot(), "java.lang.Thread", "setName", //$NON-NLS-1$ //$NON-NLS-2$

+						"(Ljava/lang/String;)V", -1, -1, -1, 0, false, null); //$NON-NLS-1$

+				bp.setPersisted(false);

+				bp.addBreakpointListener(ThreadNameChangeListener.ID_THREAD_CHANGE_NAME_LISTENER);

+				setThreadNameChangeBreakpoint(bp);

+			}

+			catch (CoreException e) {

+				status.add(e.getStatus());

+			}

+

 			if (status.getChildren().length == 0) {

 				return Status.OK_STATUS;

 			}

@@ -328,6 +346,15 @@
 				}

 				notifyTargets(breakpoint, kind);

 			}

+		} else if (property.equals(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES)) {

+			IBreakpoint breakpoint = getThreadNameChangeBreakpoint();

+			if (breakpoint != null) {

+				int kind = REMOVED;

+				if (isListeningOnThreadNameChanges()) {

+					kind = ADDED;

+				}

+				notifyTargets(breakpoint, kind);

+			}

 		} else if (fgDisplayOptions.contains(property)) {

 			variableViewSettingsChanged();

 		} else if (isUseFilterProperty(property)) {

@@ -397,6 +424,14 @@
 		return JDIDebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS);

 	}

 

+	/**

+	 * Returns whether listening on thread name changes is enabled

+	 *

+	 * @return whether listening on thread name changes is enabled

+	 */

+	public boolean isListeningOnThreadNameChanges() {

+		return JDIDebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IJDIPreferencesConstants.PREF_LISTEN_ON_THREAD_NAME_CHANGES);

+	}

 

 	/**

 	 * Sets the breakpoint used to suspend on uncaught exceptions

@@ -408,6 +443,25 @@
 	}

 

 	/**

+	 * Sets the breakpoint used to listen to thread name changes

+	 *

+	 * @param breakpoint

+	 *            method entry breakpoint

+	 */

+	private void setThreadNameChangeBreakpoint(IJavaMethodEntryBreakpoint breakpoint) {

+		fThreadNameChangeBreakpoint = breakpoint;

+	}

+

+	/**

+	 * Returns the breakpoint used to listen to thread name changes

+	 *

+	 * @return method entry breakpoint

+	 */

+	public IJavaMethodEntryBreakpoint getThreadNameChangeBreakpoint() {

+		return fThreadNameChangeBreakpoint;

+	}

+

+	/**

 	 * Returns the breakpoint used to suspend on uncaught exceptions

 	 *

 	 * @return exception breakpoint

@@ -517,6 +571,11 @@
 						notifyTarget(javaTarget, getSuspendOnCompilationErrorBreakpoint(), ADDED);

 					}

 

+					// thread name change

+					if (isListeningOnThreadNameChanges()) {

+						notifyTarget(javaTarget, getThreadNameChangeBreakpoint(), ADDED);

+					}

+

 					// uncaught exception breakpoint

 					if (isSuspendOnUncaughtExceptions()) {

 						ILaunchConfiguration launchConfiguration = javaTarget.getLaunch().getLaunchConfiguration();

diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugPreferencePage.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugPreferencePage.java
index d4543af..d62f968 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugPreferencePage.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDebugPreferencePage.java
@@ -11,8 +11,10 @@
 package org.eclipse.jdt.internal.debug.ui;
 
 
+import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.preferences.DefaultScope;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
 import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.debug.internal.ui.SWTFactory;
 import org.eclipse.jdt.debug.core.IJavaBreakpoint;
@@ -91,6 +93,7 @@
 	private Button fAlertObsoleteButton;
 	private Button fPerformHCRWithCompilationErrors;
 	private Button fShowStepResult;
+	private Button fAdvancedSourcelookup;
 
 	// Timeout preference widgets
 	private JavaDebugIntegerFieldEditor fTimeoutText;
@@ -172,6 +175,9 @@
 		SWTFactory.createVerticalSpacer(composite, 1);
 		fShowStepResult = SWTFactory.createCheckButton(composite, DebugUIMessages.JavaDebugPreferencePage_ShowStepResult_1, null, false, 1);
 
+		SWTFactory.createVerticalSpacer(composite, 1);
+		fAdvancedSourcelookup = SWTFactory.createCheckButton(composite, DebugUIMessages.JavaDebugPreferencePage_advancedSourcelookup, null, false, 1);
+
 		setValues();
 
 		fTimeoutText.setPropertyChangeListener(this);
@@ -179,15 +185,9 @@
 		return composite;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
-	 */
 	@Override
 	public void init(IWorkbench workbench) {}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.jface.preference.PreferencePage#performOk()
-	 */
 	@Override
 	public boolean performOk() {
 		IPreferenceStore store = getPreferenceStore();
@@ -214,6 +214,7 @@
 			prefs.putBoolean(JDIDebugModel.PREF_SHOW_STEP_RESULT, fShowStepResult.getSelection());
 			prefs.putInt(JDIDebugModel.PREF_REQUEST_TIMEOUT, fTimeoutText.getIntValue());
 			prefs.putBoolean(JDIDebugModel.PREF_FILTER_BREAKPOINTS_FROM_UNRELATED_SOURCES, fFilterUnrelatedBreakpoints.getSelection());
+			prefs.putBoolean(JDIDebugPlugin.PREF_ENABLE_ADVANCED_SOURCELOOKUP, fAdvancedSourcelookup.getSelection());
 			try {
 				prefs.flush();
 			}
@@ -235,9 +236,6 @@
 		return true;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
-	 */
 	@Override
 	protected void performDefaults() {
 		IPreferenceStore store = getPreferenceStore();
@@ -260,6 +258,7 @@
 			fShowStepResult.setSelection(prefs.getBoolean(JDIDebugModel.PREF_SHOW_STEP_RESULT, true));
 			fTimeoutText.setStringValue(new Integer(prefs.getInt(JDIDebugModel.PREF_REQUEST_TIMEOUT, JDIDebugModel.DEF_REQUEST_TIMEOUT)).toString());
 			fFilterUnrelatedBreakpoints.setSelection(prefs.getBoolean(JDIDebugModel.PREF_FILTER_BREAKPOINTS_FROM_UNRELATED_SOURCES, true));
+			fAdvancedSourcelookup.setSelection(prefs.getBoolean(JDIDebugPlugin.PREF_ENABLE_ADVANCED_SOURCELOOKUP, true));
 		}
 		prefs = DefaultScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN);
 		if(prefs != null) {
@@ -283,28 +282,26 @@
 		fPromptUnableToInstallBreakpoint.setSelection(store.getBoolean(IJDIPreferencesConstants.PREF_ALERT_UNABLE_TO_INSTALL_BREAKPOINT));
 		fPromptDeleteConditionalBreakpoint.setSelection(store.getBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT));
 		fOpenInspector.setSelection(store.getBoolean(IJDIPreferencesConstants.PREF_OPEN_INSPECT_POPUP_ON_EXCEPTION));
-		IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(JDIDebugPlugin.getUniqueIdentifier());
-		if(prefs != null) {
-			fEnableHCRButton.setSelection(prefs.getBoolean(JDIDebugPlugin.PREF_ENABLE_HCR, true));
-			fSuspendDuringEvaluations.setSelection(prefs.getBoolean(JDIDebugModel.PREF_SUSPEND_FOR_BREAKPOINTS_DURING_EVALUATION, true));
-			int value = prefs.getInt(JDIDebugPlugin.PREF_DEFAULT_BREAKPOINT_SUSPEND_POLICY, IJavaBreakpoint.SUSPEND_THREAD);
-			fSuspendVMorThread.select((value == IJavaBreakpoint.SUSPEND_THREAD ? 0 : 1));
-			fWatchpoint.select(prefs.getInt(JDIDebugPlugin.PREF_DEFAULT_WATCHPOINT_SUSPEND_POLICY, 0));
-			fPerformHCRWithCompilationErrors.setSelection(prefs.getBoolean(JDIDebugModel.PREF_HCR_WITH_COMPILATION_ERRORS, true));
-			fShowStepResult.setSelection(prefs.getBoolean(JDIDebugModel.PREF_SHOW_STEP_RESULT, true));
-			fTimeoutText.setStringValue(new Integer(prefs.getInt(JDIDebugModel.PREF_REQUEST_TIMEOUT, JDIDebugModel.DEF_REQUEST_TIMEOUT)).toString());
-			fFilterUnrelatedBreakpoints.setSelection(prefs.getBoolean(JDIDebugModel.PREF_FILTER_BREAKPOINTS_FROM_UNRELATED_SOURCES, true));
-		}
-		prefs = InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN);
-		if(prefs != null) {
-			fConnectionTimeoutText.setStringValue(new Integer(prefs.getInt(JavaRuntime.PREF_CONNECT_TIMEOUT,JavaRuntime.DEF_CONNECT_TIMEOUT)).toString());
-			fOnlyIncludeExportedEntries.setSelection(prefs.getBoolean(JavaRuntime.PREF_ONLY_INCLUDE_EXPORTED_CLASSPATH_ENTRIES, false));
-		}
+
+		IPreferencesService prefs = Platform.getPreferencesService();
+
+		String bundleId = JDIDebugPlugin.getUniqueIdentifier();
+		fEnableHCRButton.setSelection(prefs.getBoolean(bundleId, JDIDebugPlugin.PREF_ENABLE_HCR, true, null));
+		fSuspendDuringEvaluations.setSelection(prefs.getBoolean(bundleId, JDIDebugModel.PREF_SUSPEND_FOR_BREAKPOINTS_DURING_EVALUATION, true, null));
+		int value = prefs.getInt(bundleId, JDIDebugPlugin.PREF_DEFAULT_BREAKPOINT_SUSPEND_POLICY, IJavaBreakpoint.SUSPEND_THREAD, null);
+		fSuspendVMorThread.select((value == IJavaBreakpoint.SUSPEND_THREAD ? 0 : 1));
+		fWatchpoint.select(prefs.getInt(bundleId, JDIDebugPlugin.PREF_DEFAULT_WATCHPOINT_SUSPEND_POLICY, 0, null));
+		fPerformHCRWithCompilationErrors.setSelection(prefs.getBoolean(bundleId, JDIDebugModel.PREF_HCR_WITH_COMPILATION_ERRORS, true, null));
+		fShowStepResult.setSelection(prefs.getBoolean(bundleId, JDIDebugModel.PREF_SHOW_STEP_RESULT, true, null));
+		fTimeoutText.setStringValue(new Integer(prefs.getInt(bundleId, JDIDebugModel.PREF_REQUEST_TIMEOUT, JDIDebugModel.DEF_REQUEST_TIMEOUT, null)).toString());
+		fFilterUnrelatedBreakpoints.setSelection(prefs.getBoolean(bundleId, JDIDebugModel.PREF_FILTER_BREAKPOINTS_FROM_UNRELATED_SOURCES, true, null));
+		fAdvancedSourcelookup.setSelection(prefs.getBoolean(bundleId, JDIDebugPlugin.PREF_ENABLE_ADVANCED_SOURCELOOKUP, true, null));
+
+		bundleId = LaunchingPlugin.ID_PLUGIN;
+		fConnectionTimeoutText.setStringValue(new Integer(prefs.getInt(bundleId, JavaRuntime.PREF_CONNECT_TIMEOUT, JavaRuntime.DEF_CONNECT_TIMEOUT, null)).toString());
+		fOnlyIncludeExportedEntries.setSelection(prefs.getBoolean(bundleId, JavaRuntime.PREF_ONLY_INCLUDE_EXPORTED_CLASSPATH_ENTRIES, false, null));
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
-	 */
 	@Override
 	public void propertyChange(PropertyChangeEvent event) {
 		if (event.getProperty().equals(FieldEditor.IS_VALID)) {
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/LambdaUtils.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/LambdaUtils.java
new file mode 100644
index 0000000..c4ebe49
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/LambdaUtils.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.ui;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.ILocalVariable;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.debug.core.IJavaStackFrame;
+
+/**
+ * Utility class for Lambda Expressions and Stack frames Place holder for all Lambda operation encapsulation.
+ */
+public class LambdaUtils {
+
+	/**
+	 * Evaluates if the input frame is a lambda frame.
+	 *
+	 * @param frame
+	 *            the frame which needs to be evaluated
+	 * @return <code>True</code> if the frame is a lambda frame else return <code>False</Code>
+	 * @since 3.8
+	 */
+	public static boolean isLambdaFrame(IJavaStackFrame frame) throws DebugException {
+		return frame.isSynthetic() && frame.getName().startsWith("lambda$"); //$NON-NLS-1$
+	}
+
+	private static int indexOf(IJavaStackFrame frame, IStackFrame[] stackFrames) {
+		int j = 0;
+		boolean found = false;
+		for (; j < stackFrames.length; j++) {
+			if (stackFrames[j] == frame) {
+				found = true;
+				break;
+			}
+		}
+		if (found) {
+			return j;
+		}
+		return -1;
+	}
+
+	/**
+	 * Evaluates if the input frame is a lambda frame.
+	 *
+	 * @param frame
+	 *            the frame which needs to be evaluated
+	 * @param local
+	 *            the local variable to be found
+	 * @return <code>null</code> if loval variable not found or return the found variable
+	 * @since 3.8
+	 */
+	public static IVariable findLocalVariableFromLambdaScope(IJavaStackFrame frame, ILocalVariable local) throws DebugException, CoreException {
+		// This can be local variable defined in the lambda body
+		IVariable var = JavaDebugHover.findLocalVariable(frame, local.getElementName());
+		if (var != null) {
+			return var;
+		}
+
+		// ... or this is a local variable captured from enclosing method by the lambda expression.
+		IStackFrame[] stackFrames = frame.getThread().getStackFrames();
+		int indexOfCurrentFrame = indexOf(frame, stackFrames);
+		if (indexOfCurrentFrame < 0) {
+			// paranoia, should not happen
+			return null;
+		}
+
+		// We check frames below current if we can find the one corresponding
+		// to the enclosing method and search the variable in this frame.
+		int i = 1 + indexOfCurrentFrame;
+		IJavaElement parent = local.getParent();
+		String enclosingMethodName = parent.getElementName();
+		List<String> methodTypeNames = getArgumentTypeNames(parent);
+		for (; i < stackFrames.length; i++) {
+			IJavaStackFrame currFrame = (IJavaStackFrame) stackFrames[i];
+			String methodName = currFrame.getMethodName();
+			List<String> typeNames = currFrame.getArgumentTypeNames();
+
+			if (methodName.equals(enclosingMethodName) && typeNames.equals(methodTypeNames)) {
+				var = JavaDebugHover.findLocalVariable(currFrame, local.getElementName());
+				if (var != null) {
+					return var;
+				}
+				// we can stop searching now
+				return null;
+			}
+		}
+		return null;
+	}
+
+	private static List<String> getArgumentTypeNames(IJavaElement parent) throws CoreException {
+		if (!(parent instanceof IMethod)) {
+			return null;
+		}
+		IMethod method = (IMethod) parent;
+		IType type = method.getDeclaringType();
+		if (type == null) {
+			return null;
+		}
+		List<String> psig = new ArrayList<>();
+		String[] ptypes = method.getParameterTypes();
+		for (String ps : ptypes) {
+			@SuppressWarnings("restriction")
+			String resolvedName = org.eclipse.jdt.internal.corext.util.JavaModelUtil.getResolvedTypeName(ps, type);
+			int arrayCount = Signature.getArrayCount(ps);
+			for (int i = 0; i < arrayCount; i++) {
+				resolvedName += "[]"; //$NON-NLS-1$
+			}
+			psig.add(resolvedName);
+		}
+		return psig;
+	}
+}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java
index 3f5c4aa..b1dec99 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -161,6 +161,12 @@
 
 	public static String TracepointToggleAction_Unavailable;
 
+	public static String Override_Dependencies_title;
+	public static String Override_Dependencies_button;
+	public static String Override_Dependencies_button1;
+	public static String Override_Dependencies_label1;
+	public static String Override_Dependencies_label2;
+
 	static {
 		// load message values from bundle file
 		NLS.initializeMessages(BUNDLE_NAME, ActionMessages.class);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties
index 3bb9aa7..ab60596 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ActionMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2017 IBM Corporation and others.
+# Copyright (c) 2000, 2018 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -31,7 +31,7 @@
 Evaluate_error_message_wrapped_exception=An exception occurred: {0}
 Evaluate_error_problem_append_pattern={0}\n{1}
 Evaluate_error_title_eval_problems=Error Evaluating
-EvaluateAction_Cannot_open_Display_view=Unable to open Display View
+EvaluateAction_Cannot_open_Display_view=Unable to open Debug Shell view
 EvaluateAction__evaluation_failed__1=(evaluation failed)
 EvaluateAction__evaluation_failed__Reason=Evaluation failed. Reason(s):\n{0}
 EvaluateAction_Thread_not_suspended___unable_to_perform_evaluation__1=Thread not suspended - unable to perform evaluation.
@@ -96,7 +96,7 @@
 BreakpointLocationVerifierJob_breakpointRemoved=Breakpoint removed.
 BreakpointLocationVerifierJob_breakpointMovedToValidPosition=The breakpoint has been moved to a valid position.
 BreakpointLocationVerifierJob_breakpointSetToRightType=The breakpoint has been set to the right type.
-PopupDisplayAction_2=Move to Display View
+PopupDisplayAction_2=Move to Debug Shell view
 
 ToggleBreakpointAdapter_9=Selection does not contain a method
 ToggleBreakpointAdapter_10=Selection does not contain a field
@@ -141,4 +141,9 @@
 OpenTypeAction_2=Unable to display the selected type.
 EditClasspathEntryAction_0=Ed&it...
 ProjectSelectionDialog_0=Choose &project(s) to add:
-TracepointToggleAction_Unavailable=The operation is unavailable on the current selection.
\ No newline at end of file
+TracepointToggleAction_Unavailable=The operation is unavailable on the current selection.
+Override_Dependencies_title=Override Dependencies
+Override_Dependencies_button=&Override
+Override_Dependencies_button1=&Override Dependencies...
+Override_Dependencies_label1=Dependencies derived from the Java Build Path:
+Override_Dependencies_label2=Dependencies for launching:
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalFolderAction.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalFolderAction.java
index 7208dec..874e1e5 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalFolderAction.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalFolderAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -41,7 +41,7 @@
 		if (lastUsedPath == null) {
 			lastUsedPath= ""; //$NON-NLS-1$
 		}
-		DirectoryDialog dialog= new DirectoryDialog(getShell(), SWT.MULTI);
+		DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.MULTI | SWT.SHEET);
 		dialog.setText(ActionMessages.AddExternalFolderAction_Folder_Selection_3);
 		dialog.setFilterPath(lastUsedPath);
 		String res= dialog.open();
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalJarAction.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalJarAction.java
index 5a5b764..2892c33 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalJarAction.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/AddExternalJarAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -45,7 +45,7 @@
 		if (lastUsedPath == null) {
 			lastUsedPath = ""; //$NON-NLS-1$
 		}
-		FileDialog dialog = new FileDialog(getShell(), SWT.MULTI);
+		FileDialog dialog = new FileDialog(getShell(), SWT.MULTI | SWT.SHEET);
 		dialog.setText(ActionMessages.AddExternalJar_Jar_Selection_3);
 		dialog.setFilterExtensions(new String[] {"*.jar;*.zip","*.*"}); //$NON-NLS-1$ //$NON-NLS-2$
 		dialog.setFilterPath(lastUsedPath);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesAction.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesAction.java
new file mode 100644
index 0000000..6924ef9
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesAction.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.ui.actions;
+
+
+import org.eclipse.jdt.debug.ui.launchConfigurations.JavaClasspathTab;
+import org.eclipse.jdt.internal.debug.ui.launcher.IClasspathViewer;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.actions.SelectionListenerAction;
+
+/**
+ * Overrides the dependencies specified in the Java Build path.
+ */
+public class OverrideDependenciesAction extends RuntimeClasspathAction {
+
+	private JavaClasspathTab fTab;
+
+	/**
+	 * Constructor
+	 * @param viewer the associated classpath viewer
+	 * @param tab the tab the viewer resides in
+	 */
+	public OverrideDependenciesAction(IClasspathViewer viewer, JavaClasspathTab tab) {
+		super(ActionMessages.Override_Dependencies_button1, viewer);
+		fTab = tab;
+	}
+
+	/**
+	 * View and override dependencies.
+	 *
+	 * @see org.eclipse.jface.action.Action#run()
+	 */
+	@Override
+	public void run() {
+		OverrideDependenciesDialog dialog = new OverrideDependenciesDialog(getShell(), ActionMessages.Override_Dependencies_title, null, null, 0, new String[] {
+				ActionMessages.Override_Dependencies_button, IDialogConstants.CANCEL_LABEL }, 0, fTab.getLaunchConfiguration());
+		int returnValue = dialog.open();
+		if (returnValue == 0) {
+			getViewer().notifyChanged();
+		}
+	}
+
+	/**
+	 * @see SelectionListenerAction#updateSelection(IStructuredSelection)
+	 */
+	@Override
+	protected boolean updateSelection(IStructuredSelection selection) {
+		return true;
+	}
+}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesDialog.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesDialog.java
new file mode 100644
index 0000000..51c55b8
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/OverrideDependenciesDialog.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2018 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.ui.actions;
+
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchDelegate;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Allows the user to specify if they want to delete the working set, all the breakpoints in the working
+ * set or both
+ * @since 3.2
+ */
+public class OverrideDependenciesDialog extends MessageDialog {
+	Text fModuleArgumentsText;
+	Text fModuleArgumentsNewText;
+	ILaunchConfiguration flaunchConfiguration;
+
+
+	public OverrideDependenciesDialog(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage, int dialogImageType, String[] dialogButtonLabels, int defaultIndex, ILaunchConfiguration config) {
+		super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, defaultIndex);
+		flaunchConfiguration = config;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.MessageDialog#createCustomArea(org.eclipse.swt.widgets.Composite)
+	 */
+	@Override
+	protected Control createCustomArea(Composite parent) {
+		Composite comp = new Composite(parent, SWT.NONE);
+		comp.setLayout(new GridLayout());
+		Font font = parent.getFont();
+
+		Group group = new Group(comp, SWT.NONE);
+		GridLayout topLayout = new GridLayout();
+		group.setLayout(topLayout);
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = convertHeightInCharsToPixels(20);
+		gd.widthHint = convertWidthInCharsToPixels(70);
+		group.setLayoutData(gd);
+		group.setFont(font);
+
+
+		Label description = new Label(group, SWT.WRAP);
+		description.setText(ActionMessages.Override_Dependencies_label1);
+		fModuleArgumentsText = new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
+		gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = convertHeightInCharsToPixels(10);
+		gd.widthHint = convertWidthInCharsToPixels(60);
+		fModuleArgumentsText.setLayoutData(gd);
+
+
+		Label description1 = new Label(group, SWT.WRAP);
+		description1.setText(ActionMessages.Override_Dependencies_label2);
+		fModuleArgumentsNewText = new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
+		gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = convertHeightInCharsToPixels(10);
+		gd.widthHint = convertWidthInCharsToPixels(60);
+		fModuleArgumentsNewText.setLayoutData(gd);
+
+		String moduleCLIOptions = ""; //$NON-NLS-1$
+		try {
+			AbstractJavaLaunchConfigurationDelegate delegate = getJavaLaunchConfigurationDelegate();
+			if (delegate != null) {
+				moduleCLIOptions = delegate.getModuleCLIOptions(flaunchConfiguration);
+			}
+		} catch (CoreException e) {
+			e.printStackTrace();
+		}
+
+		fModuleArgumentsText.setText(moduleCLIOptions);
+		fModuleArgumentsText.setEditable(false);
+		try {
+			if (!flaunchConfiguration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true)) {
+				String str = flaunchConfiguration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MODULE_CLI_OPTIONS, "");//$NON-NLS-1$
+				fModuleArgumentsNewText.setText(str);
+
+			} else {
+				fModuleArgumentsNewText.setText(moduleCLIOptions);
+			}
+		}
+		catch (CoreException e) {
+			e.printStackTrace();
+		}
+		return comp;
+	}
+
+	public AbstractJavaLaunchConfigurationDelegate getJavaLaunchConfigurationDelegate() throws CoreException {
+		Set<String> modes = flaunchConfiguration.getModes();
+		modes.add(ILaunchManager.RUN_MODE);
+		AbstractJavaLaunchConfigurationDelegate delegate = null;
+		for (ILaunchDelegate launchDelegate : flaunchConfiguration.getType().getDelegates(modes)) {
+			if (launchDelegate.getDelegate() instanceof AbstractJavaLaunchConfigurationDelegate) {
+				delegate = (AbstractJavaLaunchConfigurationDelegate) launchDelegate.getDelegate();
+				break;
+			}
+		}
+		return delegate;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.MessageDialog#buttonPressed(int)
+	 */
+	@Override
+	protected void buttonPressed(int buttonId) {
+		if(buttonId == OK) {
+			// Save if overridden
+			if (!fModuleArgumentsNewText.getText().equals(fModuleArgumentsText.getText())) {
+				ILaunchConfigurationWorkingCopy workingCopy;
+				try {
+					workingCopy = flaunchConfiguration.getWorkingCopy();
+					workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, false);
+					workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MODULE_CLI_OPTIONS, fModuleArgumentsNewText.getText());
+					workingCopy.doSave();
+				}
+				catch (CoreException e) {
+					JDIDebugUIPlugin.log(e);
+				}
+			} else {
+				ILaunchConfigurationWorkingCopy workingCopy;
+				try {
+					workingCopy = flaunchConfiguration.getWorkingCopy();
+					boolean attribute = workingCopy.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true);
+					if (!attribute) {
+						workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true);
+						workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MODULE_CLI_OPTIONS, fModuleArgumentsNewText.getText());
+						workingCopy.doSave();
+					}
+
+				} catch (CoreException e) {
+					JDIDebugUIPlugin.log(e);
+				}
+			}
+
+		}
+		super.buttonPressed(buttonId);
+	}
+
+
+
+}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/RestoreDefaultEntriesAction.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/RestoreDefaultEntriesAction.java
index f05f591..f18eccb 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/RestoreDefaultEntriesAction.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/RestoreDefaultEntriesAction.java
@@ -58,6 +58,17 @@
 				copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, true);
 				getViewer().setEntries(JavaRuntime.computeUnresolvedRuntimeClasspath(copy));
 			}
+			if (!config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true)) {
+				ILaunchConfigurationWorkingCopy copy = null;
+				if (config.isWorkingCopy()) {
+					copy = (ILaunchConfigurationWorkingCopy) config;
+				} else {
+					copy = config.getWorkingCopy();
+				}
+				copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true);
+				copy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MODULE_CLI_OPTIONS, ""); //$NON-NLS-1$
+
+			}
 		}
 		catch (CoreException e) {return;}
 	}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ToggleBreakpointAdapter.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ToggleBreakpointAdapter.java
index f3d9652..8bbba84 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ToggleBreakpointAdapter.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/ToggleBreakpointAdapter.java
@@ -16,6 +16,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarker;
@@ -142,7 +143,7 @@
      * @param selection the current text selection
      * @return the <code>IType</code> for the text selection or <code>null</code>
      */
-    protected IType getType(ITextSelection selection) {
+	protected static IType getType(ITextSelection selection) {
         IMember member = ActionDelegateHelper.getDefault().getCurrentMember(selection);
         IType type = null;
         if (member instanceof IType) {
@@ -157,9 +158,9 @@
             while (type != null && !type.isBinary() && type.isLocal()) {
                 type = type.getDeclaringType();
             }
-        } catch (JavaModelException e) {
-            JDIDebugUIPlugin.log(e);
-        }
+		} catch (JavaModelException e) {
+			JDIDebugUIPlugin.log(e);
+		}
         return type;
     }
 
@@ -169,7 +170,7 @@
      * @return the corresponding <code>IType</code> for the <code>IJavaElement</code>, or <code>null</code> if there is not one.
      * @since 3.3
      */
-    protected IType getType(IJavaElement element) {
+	protected static IType getType(IJavaElement element) {
     	switch(element.getElementType()) {
 	    	case IJavaElement.FIELD: {
 	    		return ((IField)element).getDeclaringType();
@@ -186,9 +187,6 @@
     	}
     }
 
-    /* (non-Javadoc)
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
-     */
     @Override
 	public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
     	toggleLineBreakpoints(part, selection, false, null);
@@ -200,7 +198,7 @@
      * @param selection the current selection
      * @param bestMatch if we should make a best match or not
      */
-    public void toggleLineBreakpoints(final IWorkbenchPart part, final ISelection selection, final boolean bestMatch, final ValidBreakpointLocationLocator locator) {
+	public static void toggleLineBreakpoints(final IWorkbenchPart part, final ISelection selection, final boolean bestMatch, final ValidBreakpointLocationLocator locator) {
         Job job = new Job("Toggle Line Breakpoint") { //$NON-NLS-1$
             @Override
 			protected IStatus run(IProgressMonitor monitor) {
@@ -212,12 +210,6 @@
         job.schedule();
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleLineBreakpoints(IWorkbenchPart,
-     *      ISelection)
-     */
     @Override
 	public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) {
     	if (isRemote(part, selection)) {
@@ -226,12 +218,6 @@
         return selection instanceof ITextSelection;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart,
-     *      org.eclipse.jface.viewers.ISelection)
-     */
     @Override
 	public void toggleMethodBreakpoints(final IWorkbenchPart part, final ISelection finalSelection) {
         Job job = new Job("Toggle Method Breakpoints") { //$NON-NLS-1$
@@ -241,90 +227,12 @@
                     return Status.CANCEL_STATUS;
                 }
                 try {
-					BreakpointToggleUtils.report(null, part);
-                    ISelection selection = finalSelection;
-                    if(!(selection instanceof IStructuredSelection)) {
-						selection = translateToMembers(part, selection);
-                    }
-                    boolean isInterface = isInterface(selection, part);
-                    if (selection instanceof IStructuredSelection) {
-                    	IMethod[] members = getMethods((IStructuredSelection) selection, isInterface);
-                        if (members.length == 0) {
-                        	if(isInterface) {
-								BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_6, part);
-							} else {
-								BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_9, part);
-							}
-                            return Status.OK_STATUS;
-                        }
-                        IJavaBreakpoint breakpoint = null;
-                        ISourceRange range = null;
-                        Map<String, Object> attributes = null;
-                        IType type = null;
-                        String signature = null;
-                        String mname = null;
-                        for (int i = 0, length = members.length; i < length; i++) {
-                            breakpoint = getMethodBreakpoint(members[i]);
-                            if (breakpoint == null) {
-                                int start = -1;
-                                int end = -1;
-                                range = members[i].getNameRange();
-                                if (range != null) {
-                                    start = range.getOffset();
-                                    end = start + range.getLength();
-                                }
-                                attributes = new HashMap<>(10);
-                                BreakpointUtils.addJavaBreakpointAttributes(attributes, members[i]);
-                                type = members[i].getDeclaringType();
-                                signature = members[i].getSignature();
-                                mname = members[i].getElementName();
-                                if (members[i].isConstructor()) {
-                                	mname = "<init>"; //$NON-NLS-1$
-                                    if (type.isEnum()) {
-                                    	signature = "(Ljava.lang.String;I" + signature.substring(1); //$NON-NLS-1$
-                                    }
-                                }
-                                if (!type.isBinary()) {
-                                	signature = resolveMethodSignature(members[i]);
-                                    if (signature == null) {
-										BreakpointToggleUtils.report(ActionMessages.ManageMethodBreakpointActionDelegate_methodNonAvailable, part);
-                                        return Status.OK_STATUS;
-                                    }
-                                }
-								IJavaMethodBreakpoint methodBreakpoint = JDIDebugModel.createMethodBreakpoint(BreakpointUtils.getBreakpointResource(members[i]), getQualifiedName(type), mname, signature, true, false, false, -1, start, end, 0, true, attributes);
-								if (BreakpointToggleUtils.isToggleTracepoints() && finalSelection instanceof ITextSelection
-										&& part instanceof CompilationUnitEditor) {
-									String pattern = getCodeTemplate((ITextSelection) finalSelection, (CompilationUnitEditor) part);
-									if (pattern != null) {
-										pattern.trim();
-										pattern = pattern.replaceAll("\\\t", ""); //$NON-NLS-1$//$NON-NLS-2$
-										methodBreakpoint.setCondition(pattern);
-										methodBreakpoint.setConditionEnabled(true);
-										methodBreakpoint.setConditionSuspendOnTrue(true);
-									}
-									BreakpointToggleUtils.setUnsetTracepoints(false);
-								}
-                            } else {
-								if (BreakpointToggleUtils.isToggleTracepoints()) {
-									deleteTracepoint(breakpoint, part, monitor);
-									BreakpointToggleUtils.setUnsetTracepoints(false);
-								} else {
-									deleteBreakpoint(breakpoint, part, monitor);
-								}
-                            }
-                        }
-                    }
-                    else {
-						BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_4, part);
-                    	return Status.OK_STATUS;
-                    }
+					return doToggleMethodBreakpoints(part, finalSelection, monitor);
                 } catch (CoreException e) {
                     return e.getStatus();
-                }
-				finally {
+				} finally {
 					BreakpointToggleUtils.setUnsetTracepoints(false);
 				}
-                return Status.OK_STATUS;
             }
         };
         job.setPriority(Job.INTERACTIVE);
@@ -332,122 +240,194 @@
         job.schedule();
     }
 
-    /**
-     * Performs the actual toggling of the line breakpoint
+	static IStatus doToggleMethodBreakpoints(IWorkbenchPart part, ISelection finalSelection, IProgressMonitor monitor) throws CoreException {
+		BreakpointToggleUtils.report(null, part);
+		ISelection selection = finalSelection;
+		if (!(selection instanceof IStructuredSelection)) {
+			selection = translateToMembers(part, selection);
+		}
+		boolean isInterface = isInterface(selection, part);
+		if (!(selection instanceof IStructuredSelection)) {
+			BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_4, part);
+			return Status.OK_STATUS;
+		}
+		IMethod[] members = getMethods((IStructuredSelection) selection, isInterface);
+		if (members.length == 0) {
+			if (isInterface) {
+				BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_6, part);
+			} else {
+				BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_9, part);
+			}
+			return Status.OK_STATUS;
+		}
+		for (IMethod member : members) {
+			doToggleMethodBreakpoint(member, part, finalSelection, monitor);
+		}
+		return Status.OK_STATUS;
+	}
+
+	private static void doToggleMethodBreakpoint(IMethod member, IWorkbenchPart part, ISelection finalSelection, IProgressMonitor monitor) throws CoreException {
+		IJavaBreakpoint breakpoint = getMethodBreakpoint(member);
+		if (breakpoint != null) {
+			if (BreakpointToggleUtils.isToggleTracepoints()) {
+				deleteTracepoint(breakpoint, part, monitor);
+				BreakpointToggleUtils.setUnsetTracepoints(false);
+			} else {
+				deleteBreakpoint(breakpoint, part, monitor);
+			}
+			return;
+		}
+		int start = -1;
+		int end = -1;
+		ISourceRange range = member.getNameRange();
+		if (range != null) {
+			start = range.getOffset();
+			end = start + range.getLength();
+		}
+		Map<String, Object> attributes = new HashMap<>(10);
+		BreakpointUtils.addJavaBreakpointAttributes(attributes, member);
+		IType type = member.getDeclaringType();
+		String signature = member.getSignature();
+		String mname = member.getElementName();
+		if (member.isConstructor()) {
+			mname = "<init>"; //$NON-NLS-1$
+			if (type.isEnum()) {
+				signature = "(Ljava.lang.String;I" + signature.substring(1); //$NON-NLS-1$
+			}
+		}
+		if (!type.isBinary()) {
+			signature = resolveMethodSignature(member);
+			if (signature == null) {
+				BreakpointToggleUtils.report(ActionMessages.ManageMethodBreakpointActionDelegate_methodNonAvailable, part);
+				return;
+			}
+		}
+		IResource resource = BreakpointUtils.getBreakpointResource(member);
+		String qualifiedName = getQualifiedName(type);
+		IJavaMethodBreakpoint methodBreakpoint = JDIDebugModel.createMethodBreakpoint(resource, qualifiedName, mname, signature, true, false, false, -1, start, end, 0, true, attributes);
+		if (BreakpointToggleUtils.isToggleTracepoints() && finalSelection instanceof ITextSelection && part instanceof CompilationUnitEditor) {
+			String pattern = getCodeTemplate((ITextSelection) finalSelection, (CompilationUnitEditor) part);
+			if (pattern != null) {
+				pattern = pattern.trim();
+				pattern = pattern.replaceAll("\\\t", ""); //$NON-NLS-1$//$NON-NLS-2$
+				methodBreakpoint.setCondition(pattern);
+				methodBreakpoint.setConditionEnabled(true);
+				methodBreakpoint.setConditionSuspendOnTrue(true);
+			}
+			BreakpointToggleUtils.setUnsetTracepoints(false);
+		}
+	}
+
+	/**
+	 * Performs the actual toggling of the line breakpoint
      * @param selection the current selection (from the editor or view)
      * @param part the active part
      * @param locator the locator, may be <code>null</code>
      * @param bestMatch if we should consider the best match rather than an exact match
      * @param monitor progress reporting
-     * @return the status of the toggle
-     * @since 3.8
-     */
-	IStatus doLineBreakpointToggle(ISelection selection, IWorkbenchPart part, ValidBreakpointLocationLocator locator, boolean bestMatch, IProgressMonitor monitor) {
+	 * @return the status of the toggle
+	 * @since 3.8
+	 */
+	static IStatus doLineBreakpointToggle(ISelection selection, IWorkbenchPart part, ValidBreakpointLocationLocator locator, boolean bestMatch, IProgressMonitor monitor) {
 		ITextEditor editor = getTextEditor(part);
-        if (editor != null && selection instanceof ITextSelection) {
-            if (monitor.isCanceled()) {
+		if (editor == null || !(selection instanceof ITextSelection)) {
+			return Status.CANCEL_STATUS;
+		}
+		if (monitor.isCanceled()) {
+			return Status.CANCEL_STATUS;
+		}
+		ITextSelection tsel = (ITextSelection) selection;
+		if (tsel.getStartLine() < 0) {
+			return Status.CANCEL_STATUS;
+		}
+		try {
+			BreakpointToggleUtils.report(null, part);
+			ISelection sel = selection;
+			if (!(selection instanceof IStructuredSelection)) {
+				sel = translateToMembers(part, selection);
+			}
+			if (!(sel instanceof IStructuredSelection)) {
+				BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_3, part);
+				return Status.OK_STATUS;
+			}
+			IMember member = (IMember) ((IStructuredSelection) sel).getFirstElement();
+			IType type = null;
+			if (member.getElementType() == IJavaElement.TYPE) {
+				type = (IType) member;
+			} else {
+				type = member.getDeclaringType();
+			}
+			if (type == null) {
+				IStatus status = new Status(IStatus.INFO, DebugUIPlugin.getUniqueIdentifier(), ActionMessages.ToggleBreakpointAdapter_ErrorMessage);
+				Display.getDefault().asyncExec(() -> ErrorDialog.openError(JDIDebugUIPlugin.getShell(), ActionMessages.ToggleBreakpointAdapter_ErrorTitle, null, status));
+				return status;
+			}
+			if (locator == null && BreakpointToggleUtils.isToggleTracepoints()) {
+				CompilationUnit cUnit = parseCompilationUnit(type.getTypeRoot());
+				locator = new ValidBreakpointLocationLocator(cUnit, tsel.getStartLine() + 1, true, bestMatch);
+				cUnit.accept(locator);
+			}
+			String tname = null;
+			IJavaProject project = type.getJavaProject();
+			if (locator == null || (project != null && !project.isOnClasspath(type))) {
+				tname = createQualifiedTypeName(type);
+			} else {
+				tname = locator.getFullyQualifiedTypeName();
+			}
+			if (tname == null) {
 				return Status.CANCEL_STATUS;
-            }
-            ITextSelection tsel = (ITextSelection) selection;
-            if(tsel.getStartLine() < 0) {
+			}
+			IResource resource = BreakpointUtils.getBreakpointResource(type);
+			int lnumber = locator == null ? tsel.getStartLine() + 1 : locator.getLineLocation();
+			IJavaLineBreakpoint existingBreakpoint = JDIDebugModel.lineBreakpointExists(resource, tname, lnumber);
+			if (existingBreakpoint != null) {
+				if (BreakpointToggleUtils.isToggleTracepoints()) {
+					deleteTracepoint(existingBreakpoint, editor, monitor);
+					BreakpointToggleUtils.setUnsetTracepoints(false);
+				} else {
+					deleteBreakpoint(existingBreakpoint, editor, monitor);
+				}
+				return Status.OK_STATUS;
+			}
+			Map<String, Object> attributes = new HashMap<>(10);
+			IDocumentProvider documentProvider = editor.getDocumentProvider();
+			if (documentProvider == null) {
 				return Status.CANCEL_STATUS;
-            }
-            try {
-				BreakpointToggleUtils.report(null, part);
-                ISelection sel = selection;
-            	if(!(selection instanceof IStructuredSelection)) {
-					sel = translateToMembers(part, selection);
-            	}
-            	if(sel instanceof IStructuredSelection) {
-                	IMember member = (IMember) ((IStructuredSelection)sel).getFirstElement();
-                	IType type = null;
-                	if(member.getElementType() == IJavaElement.TYPE) {
-                		type = (IType) member;
-                	}
-                	else {
-                		type = member.getDeclaringType();
-                	}
-					if (type == null) {
-						IStatus status = new Status(IStatus.INFO, DebugUIPlugin.getUniqueIdentifier(), ActionMessages.ToggleBreakpointAdapter_ErrorMessage);
-						 Display.getDefault().asyncExec(new Runnable() {
-							@Override
-							public void run() {
-								ErrorDialog.openError(JDIDebugUIPlugin.getShell(), ActionMessages.ToggleBreakpointAdapter_ErrorTitle, null, status);
-							}
-						});
-						return status;
-					}
-					if (locator == null && BreakpointToggleUtils.isToggleTracepoints()) {
-						CompilationUnit cUnit = parseCompilationUnit(type.getTypeRoot());
-						locator = new ValidBreakpointLocationLocator(cUnit, tsel.getStartLine() + 1, true, bestMatch);
-						cUnit.accept(locator);
-					}
-                	String tname = null;
-                	IJavaProject project = type.getJavaProject();
-                	if (locator == null || (project != null && !project.isOnClasspath(type))) {
-						tname = createQualifiedTypeName(type);
-                	} else {
-                		tname = locator.getFullyQualifiedTypeName();
-                	}
-					if (tname == null) {
-						return Status.CANCEL_STATUS;
-					}
-                	IResource resource = BreakpointUtils.getBreakpointResource(type);
-					int lnumber = locator == null ? tsel.getStartLine() + 1 : locator.getLineLocation();
-					IJavaLineBreakpoint existingBreakpoint = JDIDebugModel.lineBreakpointExists(resource, tname, lnumber);
-					if (existingBreakpoint != null) {
-						if (BreakpointToggleUtils.isToggleTracepoints()) {
-							deleteTracepoint(existingBreakpoint, editor, monitor);
-							BreakpointToggleUtils.setUnsetTracepoints(false);
-						} else {
-							deleteBreakpoint(existingBreakpoint, editor, monitor);
-						}
-						return Status.OK_STATUS;
-					}
-					Map<String, Object> attributes = new HashMap<>(10);
-					IDocumentProvider documentProvider = editor.getDocumentProvider();
-					if (documentProvider == null) {
-					    return Status.CANCEL_STATUS;
-					}
-					IDocument document = documentProvider.getDocument(editor.getEditorInput());
-					int charstart = -1, charend = -1;
-					try {
-						IRegion line = document.getLineInformation(lnumber - 1);
-						charstart = line.getOffset();
-						charend = charstart + line.getLength();
-					}
-					catch (BadLocationException ble) {JDIDebugUIPlugin.log(ble);}
-					BreakpointUtils.addJavaBreakpointAttributes(attributes, type);
-					IJavaLineBreakpoint breakpoint = JDIDebugModel.createLineBreakpoint(resource, tname, lnumber, charstart, charend, 0, true, attributes);
-					if (BreakpointToggleUtils.isToggleTracepoints() && selection instanceof ITextSelection && part instanceof CompilationUnitEditor) {
-						String pattern = getCodeTemplate((ITextSelection) selection, (CompilationUnitEditor) part);
-						if (pattern != null) {
-							pattern.trim();
-							pattern = pattern.replaceAll("\\\t", ""); //$NON-NLS-1$//$NON-NLS-2$
-							breakpoint.setCondition(pattern);
-							breakpoint.setConditionEnabled(true);
-							breakpoint.setConditionSuspendOnTrue(true);
-						}
+			}
+			IDocument document = documentProvider.getDocument(editor.getEditorInput());
+			int charstart = -1, charend = -1;
+			try {
+				IRegion line = document.getLineInformation(lnumber - 1);
+				charstart = line.getOffset();
+				charend = charstart + line.getLength();
+			} catch (BadLocationException ble) {
+				JDIDebugUIPlugin.log(ble);
+			}
+			BreakpointUtils.addJavaBreakpointAttributes(attributes, type);
+			IJavaLineBreakpoint breakpoint = JDIDebugModel.createLineBreakpoint(resource, tname, lnumber, charstart, charend, 0, true, attributes);
+			if (BreakpointToggleUtils.isToggleTracepoints() && selection instanceof ITextSelection && part instanceof CompilationUnitEditor) {
+				String pattern = getCodeTemplate((ITextSelection) selection, (CompilationUnitEditor) part);
+				if (pattern != null) {
+					pattern = pattern.trim();
+					pattern = pattern.replaceAll("\\\t", ""); //$NON-NLS-1$//$NON-NLS-2$
+					breakpoint.setCondition(pattern);
+					breakpoint.setConditionEnabled(true);
+					breakpoint.setConditionSuspendOnTrue(true);
+				}
 
-						BreakpointToggleUtils.setUnsetTracepoints(false);
-					}
-					if (locator == null) {
-						new BreakpointLocationVerifierJob(document, parseCompilationUnit(type.getTypeRoot()), breakpoint, lnumber, tname, type, editor, bestMatch).schedule();
-					}
-					if (BreakpointToggleUtils.isToggleTracepoints()) {
-						BreakpointToggleUtils.setUnsetTracepoints(false);
-					}
-                }
-                else {
-					BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_3, part);
-                	return Status.OK_STATUS;
-                }
-            }
-            catch (CoreException ce) {return ce.getStatus();}
-			finally {
 				BreakpointToggleUtils.setUnsetTracepoints(false);
 			}
-        }
+			if (locator == null) {
+				new BreakpointLocationVerifierJob(document, parseCompilationUnit(type.getTypeRoot()), breakpoint, lnumber, tname, type, editor, bestMatch).schedule();
+			}
+			if (BreakpointToggleUtils.isToggleTracepoints()) {
+				BreakpointToggleUtils.setUnsetTracepoints(false);
+			}
+		} catch (CoreException ce) {
+			return ce.getStatus();
+		} finally {
+			BreakpointToggleUtils.setUnsetTracepoints(false);
+		}
         return Status.OK_STATUS;
     }
 
@@ -457,7 +437,7 @@
      * @param selection the current selection
      * @since 3.3
      */
-    public void toggleClassBreakpoints(final IWorkbenchPart part, final ISelection selection) {
+	public static void toggleClassBreakpoints(final IWorkbenchPart part, final ISelection selection) {
     	Job job = new Job("Toggle Class Load Breakpoints") { //$NON-NLS-1$
 			@Override
 			protected IStatus run(IProgressMonitor monitor) {
@@ -465,43 +445,10 @@
                     return Status.CANCEL_STATUS;
                 }
                 try {
-					BreakpointToggleUtils.report(null, part);
-                	ISelection sel = selection;
-                	if(!(selection instanceof IStructuredSelection)) {
-						sel = translateToMembers(part, selection);
-                	}
-                	if(isInterface(sel, part)) {
-						BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_1, part);
-                    	return Status.OK_STATUS;
-                    }
-					if(sel instanceof IStructuredSelection) {
-						IMember member = (IMember)((IStructuredSelection)sel).getFirstElement();
-						IType type = (IType) member;
-						IJavaBreakpoint existing= getClassLoadBreakpoint(type);
-						if (existing != null) {
-							deleteBreakpoint(existing, part, monitor);
-							return Status.OK_STATUS;
-						}
-						HashMap<String, Object> map = new HashMap<>(10);
-						BreakpointUtils.addJavaBreakpointAttributes(map, type);
-						ISourceRange range= type.getNameRange();
-						int start = -1;
-						int end = -1;
-						if (range != null) {
-							start = range.getOffset();
-							end = start + range.getLength();
-						}
-						JDIDebugModel.createClassPrepareBreakpoint(BreakpointUtils.getBreakpointResource(member), getQualifiedName(type), IJavaClassPrepareBreakpoint.TYPE_CLASS, start, end, true, map);
-					}
-					else {
-						BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_0, part);
-						return Status.OK_STATUS;
-					}
-				}
-                catch (CoreException e) {
+					return doToggleClassBreakpoints(part, selection, monitor);
+				} catch (CoreException e) {
 					return e.getStatus();
 				}
-				return Status.OK_STATUS;
 			}
     	};
     	job.setPriority(Job.INTERACTIVE);
@@ -509,6 +456,42 @@
     	job.schedule();
     }
 
+	static IStatus doToggleClassBreakpoints(IWorkbenchPart part, ISelection selection, IProgressMonitor monitor) throws CoreException {
+		BreakpointToggleUtils.report(null, part);
+		ISelection sel = selection;
+		if (!(selection instanceof IStructuredSelection)) {
+			sel = translateToMembers(part, selection);
+		}
+		if (isInterface(sel, part)) {
+			BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_1, part);
+			return Status.OK_STATUS;
+		}
+		if (!(sel instanceof IStructuredSelection)) {
+			BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_0, part);
+			return Status.OK_STATUS;
+		}
+		IMember member = (IMember) ((IStructuredSelection) sel).getFirstElement();
+		IType type = (IType) member;
+		IJavaBreakpoint existing = getClassLoadBreakpoint(type);
+		if (existing != null) {
+			deleteBreakpoint(existing, part, monitor);
+			return Status.OK_STATUS;
+		}
+		HashMap<String, Object> map = new HashMap<>(10);
+		BreakpointUtils.addJavaBreakpointAttributes(map, type);
+		ISourceRange range = type.getNameRange();
+		int start = -1;
+		int end = -1;
+		if (range != null) {
+			start = range.getOffset();
+			end = start + range.getLength();
+		}
+		IResource resource = BreakpointUtils.getBreakpointResource(member);
+		String qualifiedName = getQualifiedName(type);
+		JDIDebugModel.createClassPrepareBreakpoint(resource, qualifiedName, IJavaClassPrepareBreakpoint.TYPE_CLASS, start, end, true, map);
+		return Status.OK_STATUS;
+	}
+
     /**
      * Returns the class load breakpoint for the specified type or null if none found
      * @param type the type to search for a class load breakpoint for
@@ -516,7 +499,7 @@
      * @throws CoreException
      * @since 3.3
      */
-	protected IJavaBreakpoint getClassLoadBreakpoint(IType type) throws CoreException {
+	protected static IJavaBreakpoint getClassLoadBreakpoint(IType type) throws CoreException {
     	IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(JDIDebugModel.getPluginIdentifier());
     	for (int i = 0; i < breakpoints.length; i++) {
 			IJavaBreakpoint breakpoint= (IJavaBreakpoint)breakpoints[i];
@@ -536,30 +519,32 @@
      * @return the binary name for the given {@link IType}
      * @since 3.6
      */
-    String getQualifiedName(IType type) throws JavaModelException {
+	static String getQualifiedName(IType type) throws JavaModelException {
     	IJavaProject project = type.getJavaProject();
-    	if (project != null && project.isOnClasspath(type) && needsBindings(type)) {
-			CompilationUnit cuNode = parseCompilationUnit(type.getTypeRoot());
-    		ISourceRange nameRange = type.getNameRange();
-    		if (SourceRange.isAvailable(nameRange)) {
-				ASTNode node = NodeFinder.perform(cuNode, nameRange);
-				if (node instanceof SimpleName) {
-					IBinding binding;
-					if (node.getLocationInParent() == SimpleType.NAME_PROPERTY &&
-							node.getParent().getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) {
-						binding = ((ClassInstanceCreation) node.getParent().getParent()).resolveTypeBinding();
-					} else {
-						binding = ((SimpleName) node).resolveBinding();
-					}
-					if (binding instanceof ITypeBinding) {
-			    		String name = ((ITypeBinding) binding).getBinaryName();
-			    		if (name != null) {
-			    			return name;
-			    		}
-					}
-				}
-    		}
-    	}
+		if (project == null || !project.isOnClasspath(type) || !needsBindings(type)) {
+			return createQualifiedTypeName(type);
+		}
+		CompilationUnit cuNode = parseCompilationUnit(type.getTypeRoot());
+		ISourceRange nameRange = type.getNameRange();
+		if (cuNode == null || !SourceRange.isAvailable(nameRange)) {
+			return createQualifiedTypeName(type);
+		}
+		ASTNode node = NodeFinder.perform(cuNode, nameRange);
+		if (!(node instanceof SimpleName)) {
+			return createQualifiedTypeName(type);
+		}
+		IBinding binding;
+		if (node.getLocationInParent() == SimpleType.NAME_PROPERTY && node.getParent().getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY) {
+			binding = ((ClassInstanceCreation) node.getParent().getParent()).resolveTypeBinding();
+		} else {
+			binding = ((SimpleName) node).resolveBinding();
+		}
+		if (binding instanceof ITypeBinding) {
+			String name = ((ITypeBinding) binding).getBinaryName();
+			if (name != null) {
+				return name;
+			}
+		}
 		return createQualifiedTypeName(type);
     }
 
@@ -570,7 +555,7 @@
      * @throws JavaModelException
      * @since 3.6
      */
-    boolean needsBindings(IType type) throws JavaModelException {
+	static boolean needsBindings(IType type) throws JavaModelException {
     	if(type.isMember()) {
     		if(type.isLocal() && !type.isAnonymous()) {
     			return true;
@@ -597,7 +582,7 @@
      * @return the package qualified name
      * @since 3.3
      */
-    String createQualifiedTypeName(IType type) {
+	static String createQualifiedTypeName(IType type) {
     	String tname = pruneAnonymous(type);
     	try {
     		String packName = null;
@@ -624,7 +609,7 @@
      * @return the compiled type name from the given {@link IType} with all occurrences of anonymous inner types removed
      * @since 3.4
      */
-    private String pruneAnonymous(IType type) {
+	private static String pruneAnonymous(IType type) {
     	StringBuffer buffer = new StringBuffer();
     	IJavaElement parent = type;
     	while(parent != null) {
@@ -651,7 +636,7 @@
      * @return the corresponding <code>IJavaElement</code>
      * @since 3.3
      */
-    private IJavaElement getJavaElement(IEditorInput input) {
+	private static IJavaElement getJavaElement(IEditorInput input) {
     	IJavaElement je = JavaUI.getEditorInputJavaElement(input);
     	if(je != null) {
     		return je;
@@ -660,12 +645,6 @@
     	return DebugWorkingCopyManager.getWorkingCopy(input, false);
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart,
-     *      org.eclipse.jface.viewers.ISelection)
-     */
     @Override
 	public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) {
     	if (isRemote(part, selection)) {
@@ -678,7 +657,6 @@
         return (selection instanceof ITextSelection) && isMethod((ITextSelection) selection, part);
     }
 
-
 	/**
 	 * Returns whether the given part/selection is remote (viewing a repository)
 	 *
@@ -686,7 +664,7 @@
 	 * @param selection
 	 * @return
 	 */
-    protected boolean isRemote(IWorkbenchPart part, ISelection selection) {
+	protected static boolean isRemote(IWorkbenchPart part, ISelection selection) {
     	if (selection instanceof IStructuredSelection) {
 			IStructuredSelection ss = (IStructuredSelection) selection;
 			Object element = ss.getFirstElement();
@@ -712,7 +690,7 @@
      * @param part workbench part
      * @return text editor part or <code>null</code>
      */
-    protected ITextEditor getTextEditor(IWorkbenchPart part) {
+	protected static ITextEditor getTextEditor(IWorkbenchPart part) {
     	if (part instanceof ITextEditor) {
     		return (ITextEditor) part;
     	}
@@ -724,7 +702,7 @@
      * @param selection the selection to get the methods from
      * @return an array of the methods from the selection or an empty array
      */
-    protected IMethod[] getMethods(IStructuredSelection selection,  boolean isInterace) {
+	protected static IMethod[] getMethods(IStructuredSelection selection, boolean isInterace) {
         if (selection.isEmpty()) {
             return new IMethod[0];
         }
@@ -755,7 +733,7 @@
      * @param selection the selection to get the methods from
      * @return an array of the methods from the selection or an empty array
      */
-    protected IMethod[] getInterfaceMethods(IStructuredSelection selection) {
+	protected static IMethod[] getInterfaceMethods(IStructuredSelection selection) {
         if (selection.isEmpty()) {
             return new IMethod[0];
         }
@@ -782,7 +760,7 @@
      * @param part the associated workbench part
      * @return true if the selection is a valid method, false otherwise
      */
-	private boolean isMethod(ITextSelection selection, IWorkbenchPart part) {
+	private static boolean isMethod(ITextSelection selection, IWorkbenchPart part) {
 		ITextEditor editor = getTextEditor(part);
 		if (editor != null) {
 			IJavaElement element = getJavaElement(editor.getEditorInput());
@@ -819,7 +797,7 @@
      * @return list of <code>IField</code> and <code>IJavaFieldVariable</code>, possibly empty
      * @throws CoreException
      */
-    protected List<Object> getFields(IStructuredSelection selection) throws CoreException {
+	protected static List<Object> getFields(IStructuredSelection selection) throws CoreException {
         if (selection.isEmpty()) {
             return Collections.EMPTY_LIST;
         }
@@ -847,7 +825,7 @@
      * @return true if the selection is part of an interface, false otherwise
      * @since 3.2
      */
-    private boolean isInterface(ISelection selection, IWorkbenchPart part) {
+	private static boolean isInterface(ISelection selection, IWorkbenchPart part) {
 		try {
 			ISelection sel = selection;
 			if(!(sel instanceof IStructuredSelection)) {
@@ -881,7 +859,7 @@
      * @return true if the text selection is a valid field for a watchpoint, false otherwise
      * @since 3.3
      */
-    private boolean isField(ITextSelection selection, IWorkbenchPart part) {
+	private static boolean isField(ITextSelection selection, IWorkbenchPart part) {
 		ITextEditor editor = getTextEditor(part);
     	if(editor != null) {
 			IJavaElement element = getJavaElement(editor.getEditorInput());
@@ -907,34 +885,28 @@
      * @param selection the current selection
      * @return true if the selection is a field false otherwise
      */
-    private boolean isFields(IStructuredSelection selection) {
-        if (!selection.isEmpty()) {
-        	try {
-	            Iterator<?> iterator = selection.iterator();
-	            while (iterator.hasNext()) {
-	                Object thing = iterator.next();
-	                if (thing instanceof IField) {
-	                	int flags = ((IField)thing).getFlags();
-	                	return !Flags.isFinal(flags) & !(Flags.isFinal(flags) & Flags.isStatic(flags));
-	                }
-	                else if(thing instanceof IJavaFieldVariable) {
-	                	IJavaFieldVariable fv = (IJavaFieldVariable)thing;
-	                	return !fv.isFinal() & !(fv.isFinal() & fv.isStatic());
-	                }
-	            }
-        	}
-        	catch(JavaModelException e) {return false;}
-        	catch(DebugException de) {return false;}
+	private static boolean isFields(IStructuredSelection selection) {
+		if (selection.isEmpty()) {
+			return false;
         }
+		try {
+			Iterator<?> iterator = selection.iterator();
+			while (iterator.hasNext()) {
+				Object thing = iterator.next();
+				if (thing instanceof IField) {
+					int flags = ((IField) thing).getFlags();
+					return !Flags.isFinal(flags);
+				} else if (thing instanceof IJavaFieldVariable) {
+					IJavaFieldVariable fv = (IJavaFieldVariable) thing;
+					return !fv.isFinal();
+				}
+			}
+		} catch (JavaModelException | DebugException e) {
+			return false;
+		}
         return false;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleWatchpoints(org.eclipse.ui.IWorkbenchPart,
-     *      org.eclipse.jface.viewers.ISelection)
-     */
     @Override
 	public void toggleWatchpoints(final IWorkbenchPart part, final ISelection finalSelection) {
         Job job = new Job("Toggle Watchpoints") { //$NON-NLS-1$
@@ -943,86 +915,11 @@
                 if (monitor.isCanceled()) {
                     return Status.CANCEL_STATUS;
                 }
-                try {
-					BreakpointToggleUtils.report(null, part);
-                    ISelection selection = finalSelection;
-                    if(!(selection instanceof IStructuredSelection)) {
-						selection = translateToMembers(part, finalSelection);
-                    }
-                    if(isInterface(selection, part)) {
-						BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_5, part);
-                		return Status.OK_STATUS;
-                	}
-                    boolean allowed = false;
-	                if (selection instanceof IStructuredSelection) {
-	                	List<Object> fields = getFields((IStructuredSelection) selection);
-	                    if (fields.isEmpty()) {
-							BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_10, part);
-	                        return Status.OK_STATUS;
-	                    }
-	                    Iterator<Object> theFields = fields.iterator();
-	                    IField javaField = null;
-	                    IResource resource = null;
-                        String typeName = null;
-                        String fieldName = null;
-                        Object element = null;
-                        Map<String, Object> attributes = null;
-                        IJavaBreakpoint breakpoint = null;
-	                    while (theFields.hasNext()) {
-	                        element = theFields.next();
-	                        if (element instanceof IField) {
-								javaField = (IField) element;
-								IType type = javaField.getDeclaringType();
-								typeName = getQualifiedName(type);
-								fieldName = javaField.getElementName();
-								int f = javaField.getFlags();
-								boolean fin = Flags.isFinal(f);
-								if (fin) {
-									fin = javaField.getConstant() != null; // watch point is allowed if no constant value
-								}
-								allowed = !(fin) & !(Flags.isStatic(f) & fin);
-							} else if (element instanceof IJavaFieldVariable) {
-								IJavaFieldVariable var = (IJavaFieldVariable) element;
-								typeName = var.getDeclaringType().getName();
-								fieldName = var.getName();
-								boolean fin = var.isFinal();
-								if (fin) {
-									fin = javaField.getConstant() != null; // watch point is allowed if no constant value
-								}
-								allowed = !(fin) & !(var.isStatic() & fin);
-							}
-	                        breakpoint = getWatchpoint(typeName, fieldName);
-	                        if (breakpoint == null) {
-	                        	if(!allowed) {
-	                        		return doLineBreakpointToggle(finalSelection, part, null, true, monitor);
-	                        	}
-	                        	int start = -1;
-	                            int end = -1;
-	                            attributes = new HashMap<>(10);
-	                            if (javaField == null) {
-	                            	resource = ResourcesPlugin.getWorkspace().getRoot();
-	                            } else {
-	                                IType type = javaField.getDeclaringType();
-	                                ISourceRange range = javaField.getNameRange();
-	                                if (range != null) {
-	                                    start = range.getOffset();
-	                                    end = start + range.getLength();
-	                                }
-	                                BreakpointUtils.addJavaBreakpointAttributes(attributes, javaField);
-	                                resource = BreakpointUtils.getBreakpointResource(type);
-	                            }
-	                        	JDIDebugModel.createWatchpoint(resource, typeName, fieldName, -1, start, end, 0, true, attributes);
-	                        } else {
-								deleteBreakpoint(breakpoint, part, monitor);
-	                        }
-	                    }
-                    }
-                    else {
-						BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_2, part);
-                    	return Status.OK_STATUS;
-                    }
-                } catch (CoreException e) {return e.getStatus();}
-                return Status.OK_STATUS;
+				try {
+					return doToggleWatchpoints(part, finalSelection, monitor);
+				} catch (CoreException e) {
+					return e.getStatus();
+				}
             }
         };
         job.setPriority(Job.INTERACTIVE);
@@ -1030,15 +927,91 @@
         job.schedule();
     }
 
-    /**
-     * Returns any existing watchpoint for the given field, or <code>null</code> if none.
-     *
+	static IStatus doToggleWatchpoints(IWorkbenchPart part, ISelection finalSelection, IProgressMonitor monitor) throws CoreException {
+		BreakpointToggleUtils.report(null, part);
+		ISelection selection = finalSelection;
+		if (!(selection instanceof IStructuredSelection)) {
+			selection = translateToMembers(part, finalSelection);
+		}
+		if (isInterface(selection, part)) {
+			BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_5, part);
+			return Status.OK_STATUS;
+		}
+		boolean allowed = false;
+		if (!(selection instanceof IStructuredSelection)) {
+			BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_2, part);
+			return Status.OK_STATUS;
+		}
+		List<Object> fields = getFields((IStructuredSelection) selection);
+		if (fields.isEmpty()) {
+			BreakpointToggleUtils.report(ActionMessages.ToggleBreakpointAdapter_10, part);
+			return Status.OK_STATUS;
+		}
+
+		IField javaField = null;
+		String typeName = null;
+		String fieldName = null;
+
+		for (Object element : fields) {
+			if (element instanceof IField) {
+				javaField = (IField) element;
+				IType type = javaField.getDeclaringType();
+				typeName = getQualifiedName(type);
+				fieldName = javaField.getElementName();
+				int f = javaField.getFlags();
+				boolean fin = Flags.isFinal(f);
+				if (fin) {
+					fin = javaField.getConstant() != null; // watch point is allowed if no constant value
+				}
+				allowed = !fin;
+			} else if (element instanceof IJavaFieldVariable) {
+				IJavaFieldVariable var = (IJavaFieldVariable) element;
+				typeName = var.getDeclaringType().getName();
+				fieldName = var.getName();
+				boolean fin = var.isFinal();
+				if (fin) {
+					fin = javaField.getConstant() != null; // watch point is allowed if no constant value
+				}
+				allowed = !fin;
+			}
+			IJavaBreakpoint breakpoint = getWatchpoint(typeName, fieldName);
+			if (breakpoint != null) {
+				deleteBreakpoint(breakpoint, part, monitor);
+				continue;
+			}
+			if (!allowed) {
+				return doLineBreakpointToggle(finalSelection, part, null, true, monitor);
+			}
+			int start = -1;
+			int end = -1;
+			Map<String, Object> attributes = new HashMap<>(10);
+			IResource resource;
+			if (javaField == null) {
+				resource = ResourcesPlugin.getWorkspace().getRoot();
+			} else {
+				IType type = javaField.getDeclaringType();
+				ISourceRange range = javaField.getNameRange();
+				if (range != null) {
+					start = range.getOffset();
+					end = start + range.getLength();
+				}
+				BreakpointUtils.addJavaBreakpointAttributes(attributes, javaField);
+				resource = BreakpointUtils.getBreakpointResource(type);
+			}
+			JDIDebugModel.createWatchpoint(resource, typeName, fieldName, -1, start, end, 0, true, attributes);
+		}
+		return Status.OK_STATUS;
+	}
+
+	/**
+	 * Returns any existing watchpoint for the given field, or <code>null</code> if none.
+	 *
      * @param typeName fully qualified type name on which watchpoint may exist
      * @param fieldName field name
-     * @return any existing watchpoint for the given field, or <code>null</code> if none
-     * @throws CoreException
-     */
-    private IJavaWatchpoint getWatchpoint(String typeName, String fieldName) throws CoreException {
+	 * @return any existing watchpoint for the given field, or <code>null</code> if none
+	 * @throws CoreException
+	 */
+	private static IJavaWatchpoint getWatchpoint(String typeName, String fieldName) throws CoreException {
         IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
         IBreakpoint[] breakpoints = breakpointManager.getBreakpoints(JDIDebugModel.getPluginIdentifier());
         for (int i = 0; i < breakpoints.length; i++) {
@@ -1155,7 +1128,7 @@
      * @param signature
      * @return handle or <code>null</code>
      */
-    protected IMethod getMethodHandle(IEditorPart editorPart, String typeName, String methodName, String signature) throws CoreException {
+	protected static IMethod getMethodHandle(IEditorPart editorPart, String typeName, String methodName, String signature) throws CoreException {
         IJavaElement element = editorPart.getEditorInput().getAdapter(IJavaElement.class);
         IType type = null;
         if (element instanceof ICompilationUnit) {
@@ -1181,44 +1154,45 @@
      * @param element the element to get the breakpoint from
      * @return the current breakpoint from the element or <code>null</code>
      */
-    protected IJavaBreakpoint getMethodBreakpoint(IMember element) {
+	protected static IJavaBreakpoint getMethodBreakpoint(IMember element) {
         IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
         IBreakpoint[] breakpoints = breakpointManager.getBreakpoints(JDIDebugModel.getPluginIdentifier());
-        if (element instanceof IMethod) {
-            IMethod method = (IMethod) element;
-            for (int i = 0; i < breakpoints.length; i++) {
-                IBreakpoint breakpoint = breakpoints[i];
-                if (breakpoint instanceof IJavaMethodBreakpoint) {
-                    IJavaMethodBreakpoint methodBreakpoint = (IJavaMethodBreakpoint) breakpoint;
-                    IMember container = null;
-                    try {
-                        container = BreakpointUtils.getMember(methodBreakpoint);
-                    } catch (CoreException e) {
-                        JDIDebugUIPlugin.log(e);
-                        return null;
-                    }
-                    if (container == null) {
-                        try {
-                            if (method.getDeclaringType().getFullyQualifiedName().equals(methodBreakpoint.getTypeName()) &&
-                            		method.getElementName().equals(methodBreakpoint.getMethodName()) &&
-                            		methodBreakpoint.getMethodSignature().equals(resolveMethodSignature(method))) {
-                                return methodBreakpoint;
-                            }
-                        } catch (CoreException e) {
-                            JDIDebugUIPlugin.log(e);
-                        }
-                    } else {
-                        if (container instanceof IMethod) {
-                            if (method.getDeclaringType().getFullyQualifiedName().equals(container.getDeclaringType().getFullyQualifiedName())) {
-                                if (method.isSimilar((IMethod) container)) {
-                                    return methodBreakpoint;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
+		if (!(element instanceof IMethod)) {
+			return null;
         }
+		IMethod method = (IMethod) element;
+		for (IBreakpoint breakpoint : breakpoints) {
+			if (!(breakpoint instanceof IJavaMethodBreakpoint)) {
+				continue;
+			}
+			IJavaMethodBreakpoint methodBreakpoint = (IJavaMethodBreakpoint) breakpoint;
+			IMember container = null;
+			try {
+				container = BreakpointUtils.getMember(methodBreakpoint);
+			} catch (CoreException e) {
+				JDIDebugUIPlugin.log(e);
+				return null;
+			}
+			if (container == null) {
+				try {
+					if (method.getDeclaringType().getFullyQualifiedName().equals(methodBreakpoint.getTypeName())
+							&& method.getElementName().equals(methodBreakpoint.getMethodName())
+							&& methodBreakpoint.getMethodSignature().equals(resolveMethodSignature(method))) {
+						return methodBreakpoint;
+					}
+				} catch (CoreException e) {
+					JDIDebugUIPlugin.log(e);
+				}
+			} else {
+				if (container instanceof IMethod) {
+					if (method.getDeclaringType().getFullyQualifiedName().equals(container.getDeclaringType().getFullyQualifiedName())) {
+						if (method.isSimilar((IMethod) container)) {
+							return methodBreakpoint;
+						}
+					}
+				}
+			}
+		}
         return null;
     }
 
@@ -1227,28 +1201,24 @@
      * @param editor the editor to get the compilation unit from
      * @return the compilation unit or <code>null</code>
      */
-    protected CompilationUnit parseCompilationUnit(ITextEditor editor) {
+	protected static CompilationUnit parseCompilationUnit(ITextEditor editor) {
         return parseCompilationUnit(getTypeRoot(editor.getEditorInput()));
     }
 
     /**
-     * Parses the {@link ITypeRoot}.
-     * @param root the root
-     * @return the parsed {@link CompilationUnit}
-     */
-    CompilationUnit parseCompilationUnit(ITypeRoot root) {
+	 * Parses the {@link ITypeRoot}.
+	 *
+	 * @param root
+	 *            the root
+	 * @return the parsed {@link CompilationUnit} or {@code null}
+	 */
+	static CompilationUnit parseCompilationUnit(ITypeRoot root) {
     	if(root != null) {
     		return SharedASTProvider.getAST(root, SharedASTProvider.WAIT_YES, null);
         }
         return null;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleWatchpoints(org.eclipse.ui.IWorkbenchPart,
-     *      org.eclipse.jface.viewers.ISelection)
-     */
     @Override
 	public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) {
     	if (isRemote(part, selection)) {
@@ -1272,44 +1242,46 @@
      * @exception CoreException
      *                if an exception occurs
      */
-    protected ISelection translateToMembers(IWorkbenchPart part, ISelection selection) throws CoreException {
+	protected static ISelection translateToMembers(IWorkbenchPart part, ISelection selection) throws CoreException {
     	ITextEditor textEditor = getTextEditor(part);
-        if (textEditor != null && selection instanceof ITextSelection) {
-            ITextSelection textSelection = (ITextSelection) selection;
-            IEditorInput editorInput = textEditor.getEditorInput();
-            IDocumentProvider documentProvider = textEditor.getDocumentProvider();
-            if (documentProvider == null) {
-                throw new CoreException(Status.CANCEL_STATUS);
-            }
-            IDocument document = documentProvider.getDocument(editorInput);
-            int offset = textSelection.getOffset();
-            if (document != null) {
-                try {
-                    IRegion region = document.getLineInformationOfOffset(offset);
-                    int end = region.getOffset() + region.getLength();
-                    while (Character.isWhitespace(document.getChar(offset)) && offset < end) {
-                        offset++;
-                    }
-                } catch (BadLocationException e) {}
-            }
-            IMember m = null;
-            ITypeRoot root = getTypeRoot(editorInput);
-            if(root instanceof ICompilationUnit) {
-                ICompilationUnit unit = (ICompilationUnit) root;
-                synchronized (unit) {
-                    unit.reconcile(ICompilationUnit.NO_AST , false, null, null);
-                }
-            }
-            if(root != null){
-                IJavaElement e = root.getElementAt(offset);
-                if (e instanceof IMember) {
-                    m = (IMember) e;
-                }
-            }
-            if (m != null) {
-                return new StructuredSelection(m);
-            }
+		if (textEditor == null || !(selection instanceof ITextSelection)) {
+			return selection;
         }
+		ITextSelection textSelection = (ITextSelection) selection;
+		IEditorInput editorInput = textEditor.getEditorInput();
+		IDocumentProvider documentProvider = textEditor.getDocumentProvider();
+		if (documentProvider == null) {
+			throw new CoreException(Status.CANCEL_STATUS);
+		}
+		IDocument document = documentProvider.getDocument(editorInput);
+		int offset = textSelection.getOffset();
+		if (document != null) {
+			try {
+				IRegion region = document.getLineInformationOfOffset(offset);
+				int end = region.getOffset() + region.getLength();
+				while (Character.isWhitespace(document.getChar(offset)) && offset < end) {
+					offset++;
+				}
+			} catch (BadLocationException e) {
+			}
+		}
+		IMember m = null;
+		ITypeRoot root = getTypeRoot(editorInput);
+		if (root instanceof ICompilationUnit) {
+			ICompilationUnit unit = (ICompilationUnit) root;
+			synchronized (unit) {
+				unit.reconcile(ICompilationUnit.NO_AST, false, null, null);
+			}
+		}
+		if (root != null) {
+			IJavaElement e = root.getElementAt(offset);
+			if (e instanceof IMember) {
+				m = (IMember) e;
+			}
+		}
+		if (m != null) {
+			return new StructuredSelection(m);
+		}
         return selection;
     }
 
@@ -1319,7 +1291,7 @@
      * @return the type root or <code>null</code> if one cannot be derived
 	 * @since 3.4
      */
-    private ITypeRoot getTypeRoot(IEditorInput input) {
+	private static ITypeRoot getTypeRoot(IEditorInput input) {
 		ITypeRoot root = input.getAdapter(IClassFile.class);
     	if(root == null) {
     		 IWorkingCopyManager manager = JavaUI.getWorkingCopyManager();
@@ -1335,7 +1307,7 @@
      * Return the associated IField (Java model) for the given
      * IJavaFieldVariable (JDI model)
      */
-    private IField getField(IJavaFieldVariable variable) throws CoreException {
+	private static IField getField(IJavaFieldVariable variable) throws CoreException {
         String varName = null;
         try {
             varName = variable.getName();
@@ -1355,95 +1327,123 @@
         return null;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#toggleBreakpoints(org.eclipse.ui.IWorkbenchPart,
-     *      org.eclipse.jface.viewers.ISelection)
-     */
     @Override
 	public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
 		ISelection sel = translateToMembers(part, selection);
-    	if(sel instanceof IStructuredSelection) {
-    		IMember member = (IMember) ((IStructuredSelection)sel).getFirstElement();
-    		int mtype = member.getElementType();
-    		if(mtype == IJavaElement.FIELD || mtype == IJavaElement.METHOD || mtype == IJavaElement.INITIALIZER) {
-    			// remove line breakpoint if present first
-    	    	if (selection instanceof ITextSelection) {
-    				ITextSelection ts = (ITextSelection) selection;
-					IJavaLineBreakpoint breakpoint = null;
-					ITextEditor editor = getTextEditor(part);
-					IAnnotationModel annotationModel = editor.getDocumentProvider().getAnnotationModel(editor.getEditorInput());
-					IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
-					if (annotationModel != null) {
-						Iterator<Annotation> iterator = annotationModel.getAnnotationIterator();
-						while (iterator.hasNext()) {
-							Object object = iterator.next();
-							if (object instanceof SimpleMarkerAnnotation) {
-								SimpleMarkerAnnotation markerAnnotation = (SimpleMarkerAnnotation) object;
-								IMarker marker = markerAnnotation.getMarker();
-								try {
-									if (marker.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) {
-										Position position = annotationModel.getPosition(markerAnnotation);
-										int line = document.getLineOfOffset(position.getOffset());
-										if (line == ts.getStartLine()) {
-											IBreakpoint oldBreakpoint = DebugPlugin.getDefault().getBreakpointManager().getBreakpoint(marker);
-											if (oldBreakpoint instanceof IJavaLineBreakpoint) {
-												breakpoint = (IJavaLineBreakpoint) oldBreakpoint;
-												break;
-											}
-										}
-									}
-								}
-								catch (BadLocationException e) {
-									JDIDebugUIPlugin.log(e);
-								}
-							}
+		if (!(sel instanceof IStructuredSelection)) {
+			return;
+		}
+		IMember member = (IMember) ((IStructuredSelection) sel).getFirstElement();
+		int mtype = member.getElementType();
+		if (mtype == IJavaElement.FIELD || mtype == IJavaElement.METHOD || mtype == IJavaElement.INITIALIZER) {
+			toggleFieldOrMethodBreakpoints(part, selection);
+		} else if (member.getElementType() == IJavaElement.TYPE) {
+			if (BreakpointToggleUtils.isToggleTracepoints()) {
+				BreakpointToggleUtils.report(ActionMessages.TracepointToggleAction_Unavailable, part);
+				BreakpointToggleUtils.setUnsetTracepoints(false);
+				return;
+			}
+			toggleClassBreakpoints(part, sel);
+		} else {
+			// fall back to old behavior, always create a line breakpoint
+			toggleLineBreakpoints(part, selection, true, null);
+		}
+	}
+
+	private static IJavaLineBreakpoint findExistingBreakpoint(ITextEditor editor, ITextSelection ts) {
+		IDocumentProvider documentProvider = editor.getDocumentProvider();
+		if (documentProvider == null) {
+			return null;
+		}
+		IEditorInput editorInput = editor.getEditorInput();
+		IAnnotationModel annotationModel = documentProvider.getAnnotationModel(editorInput);
+		if (annotationModel == null) {
+			return null;
+		}
+		IDocument document = documentProvider.getDocument(editorInput);
+		if (document == null) {
+			return null;
+		}
+		Iterator<Annotation> iterator = annotationModel.getAnnotationIterator();
+		while (iterator.hasNext()) {
+			Object object = iterator.next();
+			if (!(object instanceof SimpleMarkerAnnotation)) {
+				continue;
+			}
+			SimpleMarkerAnnotation markerAnnotation = (SimpleMarkerAnnotation) object;
+			IMarker marker = markerAnnotation.getMarker();
+			try {
+				if (marker.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) {
+					Position position = annotationModel.getPosition(markerAnnotation);
+					int line = document.getLineOfOffset(position.getOffset());
+					if (line == ts.getStartLine()) {
+						IBreakpoint oldBreakpoint = DebugPlugin.getDefault().getBreakpointManager().getBreakpoint(marker);
+						if (oldBreakpoint instanceof IJavaLineBreakpoint) {
+							return (IJavaLineBreakpoint) oldBreakpoint;
 						}
 					}
-
-    				if (breakpoint != null) {
-						if (BreakpointToggleUtils.isToggleTracepoints()) {
-							deleteTracepoint(breakpoint, part, null);
-							BreakpointToggleUtils.setUnsetTracepoints(false);
-						} else {
-							deleteBreakpoint(breakpoint, part, null);
-						}
-    					return;
-    				}
-					CompilationUnit unit = parseCompilationUnit(getTextEditor(part));
-        			ValidBreakpointLocationLocator loc = new ValidBreakpointLocationLocator(unit, ts.getStartLine()+1, true, true);
-        			unit.accept(loc);
-        			if(loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_METHOD) {
-						toggleMethodBreakpoints(part, ts);
-        			}
-        			else if(loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_FIELD) {
-						if (BreakpointToggleUtils.isToggleTracepoints()) {
-							BreakpointToggleUtils.report(ActionMessages.TracepointToggleAction_Unavailable, part);
-							BreakpointToggleUtils.setUnsetTracepoints(false);
-							return;
-						}
-        				toggleWatchpoints(part, ts);
-        			}
-        			else if(loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_LINE) {
-        				toggleLineBreakpoints(part, ts, false, loc);
-        			}
-    			}
-    		}
-    		else if(member.getElementType() == IJavaElement.TYPE) {
-				if (BreakpointToggleUtils.isToggleTracepoints()) {
-					BreakpointToggleUtils.report(ActionMessages.TracepointToggleAction_Unavailable, part);
-					BreakpointToggleUtils.setUnsetTracepoints(false);
-					return;
 				}
-    			toggleClassBreakpoints(part, sel);
-    		}
-    		else {
-    			//fall back to old behavior, always create a line breakpoint
-    			toggleLineBreakpoints(part, selection, true, null);
-    		}
-    	}
-    }
+			} catch (BadLocationException e) {
+				JDIDebugUIPlugin.log(e);
+			} catch (CoreException e) {
+				logBadAnnotation(markerAnnotation, e);
+			}
+		}
+		return null;
+	}
+
+	private void toggleFieldOrMethodBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException {
+		if (!(selection instanceof ITextSelection)) {
+			return;
+		}
+		ITextSelection ts = (ITextSelection) selection;
+		ITextEditor editor = getTextEditor(part);
+		if (editor == null) {
+			return;
+		}
+		// remove line breakpoint if present first
+		IJavaLineBreakpoint breakpoint = findExistingBreakpoint(editor, ts);
+		if (breakpoint != null) {
+			if (BreakpointToggleUtils.isToggleTracepoints()) {
+				deleteTracepoint(breakpoint, part, null);
+				BreakpointToggleUtils.setUnsetTracepoints(false);
+			} else {
+				deleteBreakpoint(breakpoint, part, null);
+			}
+			return;
+		}
+		// no breakpoint found: we create new one
+		CompilationUnit unit = parseCompilationUnit(editor);
+		if (unit == null) {
+			JDIDebugUIPlugin.log("Failed to parse CU for: " + editor.getTitle(), new IllegalStateException()); //$NON-NLS-1$
+			return;
+		}
+		ValidBreakpointLocationLocator loc = new ValidBreakpointLocationLocator(unit, ts.getStartLine() + 1, true, true);
+		unit.accept(loc);
+		if (loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_METHOD) {
+			toggleMethodBreakpoints(part, ts);
+		} else if (loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_FIELD) {
+			if (BreakpointToggleUtils.isToggleTracepoints()) {
+				BreakpointToggleUtils.report(ActionMessages.TracepointToggleAction_Unavailable, part);
+				BreakpointToggleUtils.setUnsetTracepoints(false);
+				return;
+			}
+			toggleWatchpoints(part, ts);
+		} else if (loc.getLocationType() == ValidBreakpointLocationLocator.LOCATION_LINE) {
+			toggleLineBreakpoints(part, ts, false, loc);
+		}
+	}
+
+	/**
+	 * Additional diagnosis info for bug 528321
+	 */
+	private static void logBadAnnotation(SimpleMarkerAnnotation annotation, CoreException e) {
+		String message = "Editor annotation with non existing marker found: "; //$NON-NLS-1$
+		message += "text: " + annotation.getText(); //$NON-NLS-1$
+		message += ", type: " + annotation.getType(); //$NON-NLS-1$
+		message += ", " + annotation.getMarker(); //$NON-NLS-1$
+		JDIDebugUIPlugin.log(message, e);
+	}
 
 	/**
 	 * Deletes the given breakpoint using the operation history, which allows to undo the deletion.
@@ -1481,42 +1481,44 @@
 
 	private static void deleteTracepoint(IJavaBreakpoint breakpoint, IWorkbenchPart part, IProgressMonitor monitor) throws CoreException {
 		final Shell shell = part != null ? part.getSite().getShell() : null;
-		final boolean[] result = new boolean[] { true };
-
 		final IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(JDIDebugUIPlugin.getUniqueIdentifier());
 		boolean prompt = prefs.getBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT, true);
 
-		if (prompt && breakpoint instanceof IJavaLineBreakpoint) {
-			String condition = ((IJavaLineBreakpoint) breakpoint).getCondition();
-			boolean conditionChanged = true;
-			if (condition != null) {
-				int index = condition.indexOf(";"); //$NON-NLS-1$
-				if (index != -1) {
-					int lastIndex = condition.lastIndexOf(";"); //$NON-NLS-1$
-					if (index == lastIndex) {
-						conditionChanged = false;
-					}
+		if (!prompt || !(breakpoint instanceof IJavaLineBreakpoint)) {
+			DebugUITools.deleteBreakpoints(new IBreakpoint[] { breakpoint }, shell, monitor);
+			return;
+		}
 
-				} else {
-					if (condition.indexOf("print") != -1) { //$NON-NLS-1$
-						conditionChanged = false;
-					}
+		final boolean[] result = new boolean[] { true };
+		String condition = ((IJavaLineBreakpoint) breakpoint).getCondition();
+		boolean conditionChanged = true;
+		if (condition != null) {
+			int index = condition.indexOf(';');
+			if (index != -1) {
+				int lastIndex = condition.lastIndexOf(';');
+				if (index == lastIndex) {
+					conditionChanged = false;
+				}
+
+			} else {
+				if (condition.indexOf("print") != -1) { //$NON-NLS-1$
+					conditionChanged = false;
 				}
 			}
-			if (conditionChanged && condition != null) {
-				Display display = shell != null && !shell.isDisposed() ? shell.getDisplay() : PlatformUI.getWorkbench().getDisplay();
-				if (!display.isDisposed()) {
-					display.syncExec(new Runnable() {
-						@Override
-						public void run() {
-							MessageDialogWithToggle dialog = MessageDialogWithToggle.openOkCancelConfirm(shell, ActionMessages.ToggleBreakpointAdapter_confirmDeleteTitle, ActionMessages.ToggleBreakpointAdapter_confirmDeleteMessage, ActionMessages.ToggleBreakpointAdapter_confirmDeleteShowAgain, false, null, null);
-							if (dialog.getToggleState()) {
-								prefs.putBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT, false);
-							}
-							result[0] = dialog.getReturnCode() == IDialogConstants.OK_ID;
+		}
+		if (conditionChanged && condition != null) {
+			Display display = shell != null && !shell.isDisposed() ? shell.getDisplay() : PlatformUI.getWorkbench().getDisplay();
+			if (!display.isDisposed()) {
+				display.syncExec(new Runnable() {
+					@Override
+					public void run() {
+						MessageDialogWithToggle dialog = MessageDialogWithToggle.openOkCancelConfirm(shell, ActionMessages.ToggleBreakpointAdapter_confirmDeleteTitle, ActionMessages.ToggleBreakpointAdapter_confirmDeleteMessage, ActionMessages.ToggleBreakpointAdapter_confirmDeleteShowAgain, false, null, null);
+						if (dialog.getToggleState()) {
+							prefs.putBoolean(IJDIPreferencesConstants.PREF_PROMPT_DELETE_CONDITIONAL_BREAKPOINT, false);
 						}
-					});
-				}
+						result[0] = dialog.getReturnCode() == IDialogConstants.OK_ID;
+					}
+				});
 			}
 		}
 
@@ -1525,12 +1527,6 @@
 		}
 	}
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#canToggleBreakpoints(org.eclipse.ui.IWorkbenchPart,
-     *      org.eclipse.jface.viewers.ISelection)
-     */
     @Override
 	public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) {
     	if (isRemote(part, selection)) {
@@ -1539,40 +1535,33 @@
         return canToggleLineBreakpoints(part, selection);
     }
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension2#toggleBreakpointsWithEvent(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection, org.eclipse.swt.widgets.Event)
-	 */
 	@Override
 	public void toggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) throws CoreException {
-		if(event != null) {
-			if((event.stateMask & SWT.MOD2) > 0) {
-				ITextEditor editor = getTextEditor(part);
-				if(editor != null) {
-					IVerticalRulerInfo info = editor.getAdapter(IVerticalRulerInfo.class);
-					if(info != null) {
-						IBreakpoint bp = BreakpointUtils.getBreakpointFromEditor(editor, info);
-						if(bp != null) {
-							bp.setEnabled(!bp.isEnabled());
-							return;
-						}
+		if (event == null) {
+			toggleBreakpoints(part, selection);
+			return;
+		}
+		if ((event.stateMask & SWT.MOD2) > 0) {
+			ITextEditor editor = getTextEditor(part);
+			if (editor != null) {
+				IVerticalRulerInfo info = editor.getAdapter(IVerticalRulerInfo.class);
+				if (info != null) {
+					IBreakpoint bp = BreakpointUtils.getBreakpointFromEditor(editor, info);
+					if (bp != null) {
+						bp.setEnabled(!bp.isEnabled());
+						return;
 					}
 				}
 			}
-			else if((event.stateMask & SWT.MOD1) > 0) {
-				ITextEditor editor = getTextEditor(part);
-				if(editor != null) {
-					IVerticalRulerInfo info = editor.getAdapter(IVerticalRulerInfo.class);
-					if(info != null) {
-						IBreakpoint bp = BreakpointUtils.getBreakpointFromEditor(editor, info);
-						if(bp != null) {
-							PreferencesUtil.createPropertyDialogOn(
-									editor.getSite().getShell(),
-									bp,
-									null,
-									null,
-									null).open();
-							return;
-						}
+		} else if ((event.stateMask & SWT.MOD1) > 0) {
+			ITextEditor editor = getTextEditor(part);
+			if (editor != null) {
+				IVerticalRulerInfo info = editor.getAdapter(IVerticalRulerInfo.class);
+				if (info != null) {
+					IBreakpoint bp = BreakpointUtils.getBreakpointFromEditor(editor, info);
+					if (bp != null) {
+						PreferencesUtil.createPropertyDialogOn(editor.getSite().getShell(), bp, null, null, null).open();
+						return;
 					}
 				}
 			}
@@ -1580,9 +1569,6 @@
 		toggleBreakpoints(part, selection);
 	}
 
-	/* (non-Javadoc)
-	 * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension2#canToggleBreakpointsWithEvent(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection, org.eclipse.swt.widgets.Event)
-	 */
 	@Override
 	public boolean canToggleBreakpointsWithEvent(IWorkbenchPart part, ISelection selection, Event event) {
 		return canToggleBreakpoints(part, selection);
@@ -1595,56 +1581,55 @@
 	 * @return the type root or <code>null</code> if one cannot be derived
 	 * @since 3.8
 	 */
-	private String getCodeTemplate(ITextSelection textSelection, CompilationUnitEditor part) {
-		TemplateContextType contextType = JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(JavaContextType.ID_STATEMENTS);
-		TemplateEngine fStatementEngine = new TemplateEngine(contextType);
-		fStatementEngine.reset();
+	private static String getCodeTemplate(ITextSelection textSelection, CompilationUnitEditor part) {
 		ITextViewer viewer = part.getViewer();
-		final String[] fTemplateBuffer = new String[1];
-		fTemplateBuffer[0] = null;
-		if (viewer != null) {
-			Display.getDefault().syncExec(new Runnable() {
-				@Override
-				public void run() {
-					ITextEditor editor = getTextEditor(part);
-					if (editor != null) {
-						IJavaElement element = getJavaElement(editor.getEditorInput());
-						ICompilationUnit cunit = null;
-						IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-						IFile file = root.getFile(element.getPath());
-						cunit = JavaCore.createCompilationUnitFrom(file);
-						IDocumentProvider documentProvider = editor.getDocumentProvider();
-						if (documentProvider == null) {
-							return;
-						}
-						IDocument document = documentProvider.getDocument(editor.getEditorInput());
-						try {
-							IRegion line = document.getLineInformation(textSelection.getStartLine() + 1);
-							Point selectedRange = viewer.getSelectedRange();
-							viewer.setSelectedRange(selectedRange.x, 0);
-							fStatementEngine.complete(viewer, line.getOffset(), cunit);
-							viewer.setSelectedRange(selectedRange.x, selectedRange.y);
-							TemplateProposal[] templateProposals = fStatementEngine.getResults();
-							for (TemplateProposal templateProposal : templateProposals) {
-								Template template = templateProposal.getTemplate();
-								if (template.getName().equals("systrace")) { //$NON-NLS-1$
-									CompilationUnitContextType contextType = (CompilationUnitContextType) JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(template.getContextTypeId());
-									CompilationUnitContext context = contextType.createContext(document, line.getOffset(), 0, cunit);
-									context.setVariable("selection", EMPTY_STRING); //$NON-NLS-1$
-									context.setForceEvaluation(true);
-									fTemplateBuffer[0] = context.evaluate(template).getString();
-									return;
-								}
-							}
-						}
-						catch (BadLocationException | TemplateException e) {
-							// ignore
-						}
-					}
-				}
-			});
+		if (viewer == null) {
+			return null;
 		}
-		return fTemplateBuffer[0];
+		TemplateContextType contextType = JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(JavaContextType.ID_STATEMENTS);
+		final AtomicReference<String> templateBuffer = new AtomicReference<>();
+		Display.getDefault().syncExec(() -> doGetCodeTemplate(textSelection, part, viewer, contextType, templateBuffer));
+		return templateBuffer.get();
+	}
+
+	private static void doGetCodeTemplate(ITextSelection textSelection, CompilationUnitEditor part, ITextViewer viewer, TemplateContextType contextType, AtomicReference<String> templateBuffer) {
+		ITextEditor editor = getTextEditor(part);
+		if (editor == null) {
+			return;
+		}
+		TemplateEngine statementEngine = new TemplateEngine(contextType);
+		statementEngine.reset();
+		IJavaElement element = getJavaElement(editor.getEditorInput());
+		ICompilationUnit cunit = null;
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IFile file = root.getFile(element.getPath());
+		cunit = JavaCore.createCompilationUnitFrom(file);
+		IDocumentProvider documentProvider = editor.getDocumentProvider();
+		if (documentProvider == null) {
+			return;
+		}
+		IDocument document = documentProvider.getDocument(editor.getEditorInput());
+		try {
+			IRegion line = document.getLineInformation(textSelection.getStartLine() + 1);
+			Point selectedRange = viewer.getSelectedRange();
+			viewer.setSelectedRange(selectedRange.x, 0);
+			statementEngine.complete(viewer, line.getOffset(), cunit);
+			viewer.setSelectedRange(selectedRange.x, selectedRange.y);
+			TemplateProposal[] templateProposals = statementEngine.getResults();
+			for (TemplateProposal templateProposal : templateProposals) {
+				Template template = templateProposal.getTemplate();
+				if (template.getName().equals("systrace")) { //$NON-NLS-1$
+					CompilationUnitContextType cuContextType = (CompilationUnitContextType) JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(template.getContextTypeId());
+					CompilationUnitContext context = cuContextType.createContext(document, line.getOffset(), 0, cunit);
+					context.setVariable("selection", EMPTY_STRING); //$NON-NLS-1$
+					context.setForceEvaluation(true);
+					templateBuffer.set(context.evaluate(template).getString());
+					return;
+				}
+			}
+		} catch (BadLocationException | TemplateException e) {
+			// ignore
+		}
 	}
 
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/ThreadNameChangeListener.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/ThreadNameChangeListener.java
new file mode 100644
index 0000000..56c5b3a
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/ThreadNameChangeListener.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Andrey Loskutov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.debug.ui.breakpoints;
+
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.jdt.core.dom.Message;
+import org.eclipse.jdt.debug.core.IJavaBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaBreakpointListener;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.core.IJavaType;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jdt.internal.debug.ui.JavaDebugOptionsManager;
+
+/**
+ * Breakpoint listener extension for the "thread name change" breakpoint.
+ *
+ * @since 3.9
+ */
+public class ThreadNameChangeListener implements IJavaBreakpointListener {
+
+	public static final String ID_THREAD_CHANGE_NAME_LISTENER = JDIDebugUIPlugin.getUniqueIdentifier() + ".threadNameChangeListener"; //$NON-NLS-1$
+
+	@Override
+	public void addingBreakpoint(IJavaDebugTarget target, IJavaBreakpoint breakpoint) {
+	}
+
+	@Override
+	public void breakpointHasCompilationErrors(IJavaLineBreakpoint breakpoint, Message[] errors) {
+	}
+
+	@Override
+	public void breakpointHasRuntimeException(IJavaLineBreakpoint breakpoint, DebugException exception) {
+	}
+
+	@Override
+	public int breakpointHit(IJavaThread thread, IJavaBreakpoint breakpoint) {
+		JavaDebugOptionsManager manager = JavaDebugOptionsManager.getDefault();
+		if (!breakpoint.equals(manager.getThreadNameChangeBreakpoint())) {
+			return DONT_CARE;
+		}
+		if (manager.isListeningOnThreadNameChanges()) {
+			// notify debug view to refresh the thread name
+			DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { new DebugEvent(thread, DebugEvent.CHANGE, DebugEvent.STATE) });
+		}
+		return DONT_SUSPEND;
+	}
+
+	@Override
+	public void breakpointInstalled(IJavaDebugTarget target, IJavaBreakpoint breakpoint) {
+	}
+
+	@Override
+	public void breakpointRemoved(IJavaDebugTarget target, IJavaBreakpoint breakpoint) {
+	}
+
+	@Override
+	public int installingBreakpoint(IJavaDebugTarget target, IJavaBreakpoint breakpoint, IJavaType type) {
+		return DONT_CARE;
+	}
+
+}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.java
index f11b6f7..8745021 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.java
@@ -29,6 +29,7 @@
 	public static String DisplayView_SelectAll_description;
 	public static String DisplayView_SelectAll_label;
 	public static String DisplayView_SelectAll_tooltip;
+	public static String DisplayView_Content_Description;
 
 	public static String JavaInspectExpression_0;
 
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.properties
index d33ee06..399da44 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2006 IBM Corporation and others.
+# Copyright (c) 2000, 2018 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -23,5 +23,6 @@
 DisplayView_SelectAll_description=Select All
 DisplayView_SelectAll_label=Select &All
 DisplayView_SelectAll_tooltip=Select
+DisplayView_Content_Description=Use this area to write, run and inspect Java expressions in the context of a debug session.
 
 JavaInspectExpression_0=An exception occurred: {0}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayView.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayView.java
index e4db3d8..85c6aa7 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayView.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/display/DisplayView.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Lucas Bullen (Red Hat Inc.) - Bug 530664 - Debug Shell hint moved to content description
  *******************************************************************************/
 package org.eclipse.jdt.internal.debug.ui.display;
 
@@ -82,7 +83,6 @@
 import org.eclipse.ui.operations.RedoActionHandler;
 import org.eclipse.ui.operations.UndoActionHandler;
 import org.eclipse.ui.part.ViewPart;
-
 import org.eclipse.ui.texteditor.FindReplaceAction;
 import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
@@ -171,13 +171,13 @@
 		fSourceViewer= new JDISourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION | SWT.LEFT_TO_RIGHT);
 		fSourceViewer.configure(new DisplayViewerConfiguration());
 		fSourceViewer.getSelectionProvider().addSelectionChangedListener(getSelectionChangedListener());
-		IDocument doc= getRestoredDocument();
-		fSourceViewer.setDocument(doc);
+		fSourceViewer.setDocument(getRestoredDocument());
 		fSourceViewer.addTextInputListener(this);
 		fRestoredContents= null;
 		createActions();
 		createUndoRedoActions();
 		initializeToolBar();
+		this.setContentDescription(DisplayMessages.DisplayView_Content_Description);
 
 		// create context menu
 		MenuManager menuMgr = new MenuManager("#PopUp"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/EEVMPage.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/EEVMPage.java
index 5b47db7..5637d15 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/EEVMPage.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/EEVMPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2015 IBM Corporation and others.
+ * Copyright (c) 2007, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -146,7 +146,7 @@
 			public void widgetDefaultSelected(SelectionEvent e) {}
 			@Override
 			public void widgetSelected(SelectionEvent e) {
-				FileDialog dialog = new FileDialog(getShell());
+				FileDialog dialog = new FileDialog(getShell(), SWT.SHEET);
 				dialog.setFilterExtensions(new String[]{"*.ee"}); //$NON-NLS-1$
 				File file = getDefinitionFile();
 				String text = fEEFile.getText();
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
index afad9ef..c67cdc3 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/InstalledJREsBlock.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -845,7 +845,7 @@
 	 */
 	protected void search() {
 		// choose a root directory for the search
-		DirectoryDialog dialog = new DirectoryDialog(getShell());
+		DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.SHEET);
 		dialog.setMessage(JREMessages.InstalledJREsBlock_9);
 		dialog.setText(JREMessages.InstalledJREsBlock_10);
 		String path = dialog.open();
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java
index 6e69bdf..b86e223 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2015 IBM Corporation and others.
+ *  Copyright (c) 2000, 2017 IBM Corporation and others.
  *  All rights reserved. This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License v1.0
  *  which accompanies this distribution, and is available at
@@ -112,6 +112,8 @@
 
 	public static String VMLibraryBlock_18;
 
+	public static String VMLibraryBlock_19;
+
 	public static String JREsUpdater_0;
 
 	public static String EEVMPage_0;
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties
index 7c2f6a6..bb9eda8 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/JREMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-#  Copyright (c) 2000, 2015 IBM Corporation and others.
+#  Copyright (c) 2000, 2017 IBM Corporation and others.
 #  All rights reserved. This program and the accompanying materials
 #  are made available under the terms of the Eclipse Public License v1.0
 #  which accompanies this distribution, and is available at
@@ -98,13 +98,14 @@
 VMDetailsDialog_0=JRE Details
 VMLibraryBlock_2=JRE System Libraries:
 VMLibraryBlock_11=Source &Attachment...
-VMLibraryBlock_16=Select to add an external JAR to the list
-VMLibraryBlock_17=Select to add a JavaDoc location to the selected library
-VMLibraryBlock_18=Select to add a source attachment to the selected library
 VMLibraryBlock_12=Select to remove the selected item from the list
 VMLibraryBlock_13=Select to move the selected item up one position in the list
 VMLibraryBlock_14=Select to move the selected item down one position in the list
 VMLibraryBlock_15=Select to restore the default entries of the list
+VMLibraryBlock_16=Select to add an external JAR to the list
+VMLibraryBlock_17=Select to add a JavaDoc location to the selected library
+VMLibraryBlock_18=Select to add a source attachment to the selected library
+VMLibraryBlock_19=Libraries cannot be empty.
 VMLibraryBlock_4=U&p
 VMLibraryBlock_5=&Down
 VMLibraryBlock_6=Re&move
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/StandardVMPage.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/StandardVMPage.java
index d90b00c..7b926e4 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/StandardVMPage.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/StandardVMPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2015 IBM Corporation and others.
+ * Copyright (c) 2007, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -138,7 +138,7 @@
 			public void widgetDefaultSelected(SelectionEvent e) {}
 			@Override
 			public void widgetSelected(SelectionEvent e) {
-				DirectoryDialog dialog = new DirectoryDialog(getShell());
+				DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.SHEET);
 				File file = new File(fJRERoot.getText());
 				String text = fJRERoot.getText();
 				if (file.isFile()) {
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/VMLibraryBlock.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/VMLibraryBlock.java
index 8db0dfc..4b4597a 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/VMLibraryBlock.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/jres/VMLibraryBlock.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -200,7 +200,7 @@
 		updateButtons();
 		IStatus status = Status.OK_STATUS;
 		if (fLibraryContentProvider.getLibraries().length == 0) {
-			status = new Status(IStatus.ERROR, JDIDebugUIPlugin.getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "Libraries cannot be empty.", null); //$NON-NLS-1$
+			status = new Status(IStatus.ERROR, JDIDebugUIPlugin.getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, JREMessages.VMLibraryBlock_19, null);
 		}
 		LibraryStandin[] standins = fLibraryContentProvider.getStandins();
 		for (int i = 0; i < standins.length; i++) {
@@ -301,7 +301,7 @@
 		if (lastUsedPath == null) {
 			lastUsedPath= ""; //$NON-NLS-1$
 		}
-		FileDialog dialog= new FileDialog(fLibraryViewer.getControl().getShell(), SWT.MULTI);
+		FileDialog dialog = new FileDialog(fLibraryViewer.getControl().getShell(), SWT.MULTI | SWT.SHEET);
 		dialog.setText(JREMessages.VMLibraryBlock_10);
 		dialog.setFilterExtensions(new String[] {"*.jar;*.zip","*.*"}); //$NON-NLS-1$ //$NON-NLS-2$
 		dialog.setFilterPath(lastUsedPath);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java
index fadc389..c2fd9e5 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2017 IBM Corporation and others.
+ *  Copyright (c) 2000, 2018 IBM Corporation and others.
  *  All rights reserved. This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License v1.0
  *  which accompanies this distribution, and is available at
@@ -9,6 +9,7 @@
  *  IBM - Initial API and implementation
  *  BEA - Daniel R Somerfield - Bug 88939
  *  Remy Chi Jian Suen - Bug 221973
+ *  Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 package org.eclipse.jdt.internal.debug.ui.launcher;
 
@@ -22,6 +23,10 @@
 	public static String JavaArgumentsTab__Program_arguments__5;
 	public static String JavaArgumentsTab_Exception_occurred_reading_configuration___15;
 	public static String JavaArgumentsTab_VM_ar_guments__6;
+	public static String JavaArgumentsTab_AttributeLabel_ProgramArguments;
+	public static String JavaArgumentsTab_AttributeLabel_VMArguments;
+	public static String JavaArgumentsTab_AttributeLabel_UseAtStart;
+	public static String JavaArgumentsTab_AttributeLabel_WorkingDirectory;
 
 	public static String JavaClasspathTab_1;
 
@@ -34,6 +39,9 @@
 	public static String JavaJRETab_3;
 	public static String JavaJRETab_4;
 
+	public static String JavaJRETab_AttributeLabel_JREContainerPath;
+	public static String JavaJRETab_AttributeLabel_VMAttributes;
+
 	public static String MainMethodLabelProvider_0;
 	public static String RuntimeClasspathAdvancedDialog_6;
 	public static String RuntimeClasspathAdvancedDialog_7;
@@ -73,6 +81,13 @@
 	public static String JavaMainTab_20;
 	public static String JavaMainTab_21;
 	public static String JavaMainTab_22;
+	public static String JavaMainTab_missing_project;
+
+	public static String JavaLauncherTab_AttributeLabel_ProjectName;
+	public static String SharedJavaMainTab_AttributeLabel_MainTypeName;
+	public static String JavaMainTab_AttributeLabel_StopInMain;
+	public static String JavaMainTab_AttributeLabel_IncludeExternalJars;
+	public static String JavaMainTab_AttributeLabel_InheritedMain;
 
 	public static String JavaUISourceLocator_askagain_message;
 	public static String JavaUISourceLocator_selectprojects_message;
@@ -92,6 +107,10 @@
 	public static String JavaClasspathTab_0;
 	public static String JavaClasspathTab_Unable_to_save_classpath_1;
 	public static String JavaClasspathTab_Invalid_runtime_classpath_1;
+	public static String JavaClasspathTab_Exclude_Test_Code;
+
+	public static String JavaClasspathTab_AttributeLabel_DefaultClasspath;
+	public static String JavaClasspathTab_AttributeLabel_Classpath;
 
 	public static String JavaDependenciesTab_0;
 	public static String JavaDependenciesTab_Dependencies_3;
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties
index 8a92d36..8a67b3e 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LauncherMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-#  Copyright (c) 2000, 2017 IBM Corporation and others.
+#  Copyright (c) 2000, 2018 IBM Corporation and others.
 #  All rights reserved. This program and the accompanying materials
 #  are made available under the terms of the Eclipse Public License v1.0
 #  which accompanies this distribution, and is available at
@@ -9,12 +9,18 @@
 #     IBM Corporation - initial API and implementation
 #     BEA - Daniel R Somerfield - Bug 88939
 #     Remy Chi Jian Suen - Bug 221973
+#     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
 ###############################################################################
 
 JavaArgumentsTab__Arguments_16=Arguments
 JavaArgumentsTab__Program_arguments__5=Program &arguments:
 JavaArgumentsTab_Exception_occurred_reading_configuration___15=Exception occurred reading configuration:
 JavaArgumentsTab_VM_ar_guments__6=VM ar&guments:
+JavaArgumentsTab_AttributeLabel_ProgramArguments=Program arguments
+JavaArgumentsTab_AttributeLabel_VMArguments=VM arguments
+JavaArgumentsTab_AttributeLabel_UseAtStart=Use at start on 1st thread
+JavaArgumentsTab_AttributeLabel_WorkingDirectory=WorkingDirectory
+
 RuntimeClasspathAdvancedDialog_6=Add &Variable String:
 RuntimeClasspathAdvancedDialog_7=Va&riables...
 
@@ -43,6 +49,8 @@
 JavaJRETab_13=Cancel
 JavaJRETab_0={0} not compatible with {1} .class file compatibility: {2}
 JavaJRETab_5=&Project execution environment ''{0}'' ({1})
+JavaJRETab_AttributeLabel_JREContainerPath=JRE container path
+JavaJRETab_AttributeLabel_VMAttributes=VM attributes
 JavaMainTab_Choose_a_main__type_to_launch__12=Select &type (? = any character, * = any String, TZ = TimeZone):
 JavaMainTab_Choose_Main_Type_11=Select Main Type
 JavaApplicationLaunchShortcut_0=Select Java Application
@@ -65,6 +73,13 @@
 JavaMainTab_20=Project {0} does not exist
 JavaMainTab_21=Project {0} is closed
 JavaMainTab_22=Include in&herited mains when searching for a main class
+JavaMainTab_missing_project=Project not specified
+
+JavaLauncherTab_AttributeLabel_ProjectName=Project name
+SharedJavaMainTab_AttributeLabel_MainTypeName=Main type name
+JavaMainTab_AttributeLabel_StopInMain=Stop in main
+JavaMainTab_AttributeLabel_IncludeExternalJars= Include external JARs
+JavaMainTab_AttributeLabel_InheritedMain=Inherited main
 
 JavaUISourceLocator_askagain_message=Do &not ask again
 JavaUISourceLocator_selectprojects_message=The source of the type ''{0}'' could not be shown as the type was not found.
@@ -86,6 +101,10 @@
 JavaClasspathTab_1=Referenced project [{0}] is not accessible.
 JavaClasspathTab_Unable_to_save_classpath_1=Unable to save classpath
 JavaClasspathTab_Invalid_runtime_classpath_1=Archive does not exist: {0}
+JavaClasspathTab_Exclude_Test_Code=Exclude Test Code
+
+JavaClasspathTab_AttributeLabel_DefaultClasspath=Default classpath
+JavaClasspathTab_AttributeLabel_Classpath=Classpath
 
 JavaDependenciesTab_0=De&pendencies
 JavaDependenciesTab_Dependencies_3=Dependencies
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LocalJavaApplicationTabGroup.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LocalJavaApplicationTabGroup.java
index 9c56ef9..314a669 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LocalJavaApplicationTabGroup.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/LocalJavaApplicationTabGroup.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,19 +7,20 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 package org.eclipse.jdt.internal.debug.ui.launcher;
 
 
 import org.eclipse.debug.core.ILaunchConfiguration;
-import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationTabGroupViewer;
-import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog;
 import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
 import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.DebugUITools;
 import org.eclipse.debug.ui.EnvironmentTab;
 import org.eclipse.debug.ui.ILaunchConfigurationDialog;
 import org.eclipse.debug.ui.ILaunchConfigurationTab;
 import org.eclipse.debug.ui.ILaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.PrototypeTab;
 import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
 import org.eclipse.jdt.debug.ui.launchConfigurations.JavaArgumentsTab;
 import org.eclipse.jdt.debug.ui.launchConfigurations.JavaClasspathTab;
@@ -28,7 +29,6 @@
 import org.eclipse.jdt.debug.ui.launchConfigurations.JavaMainTab;
 import org.eclipse.jdt.launching.JavaRuntime;
 
-@SuppressWarnings("restriction")
 public class LocalJavaApplicationTabGroup extends AbstractLaunchConfigurationTabGroup {
 
 	/**
@@ -36,30 +36,17 @@
 	 */
 	@Override
 	public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
-		JavaClasspathTab tab = null;
-		if (dialog instanceof LaunchConfigurationsDialog) {
-			LaunchConfigurationTabGroupViewer tabViewer = ((LaunchConfigurationsDialog) dialog).getTabViewer();
-			if (tabViewer != null) {
-				Object input = tabViewer.getInput();
-				if (input instanceof ILaunchConfiguration) {
-					ILaunchConfiguration configuration = (ILaunchConfiguration) input;
-					if (JavaRuntime.isModularConfiguration(configuration)) {
-						tab = new JavaDependenciesTab();
-					}
-				}
-			}
-		}
-		if (tab == null) {
-			tab = new JavaClasspathTab();
-		}
+		ILaunchConfiguration configuration = DebugUITools.getLaunchConfiguration(dialog);
+		boolean isModularConfiguration = configuration != null && JavaRuntime.isModularConfiguration(configuration);
 		ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
 			new JavaMainTab(),
 			new JavaArgumentsTab(),
-			new JavaJRETab(),
-				tab,
+			new JavaJRETab(true),
+			isModularConfiguration ? new JavaDependenciesTab() : new JavaClasspathTab(),
 			new SourceLookupTab(),
 			new EnvironmentTab(),
-			new CommonTab()
+			new CommonTab(),
+			new PrototypeTab()
 		};
 		setTabs(tabs);
 	}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/SharedJavaMainTab.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/SharedJavaMainTab.java
index 3d48218..78c9744 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/SharedJavaMainTab.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/launcher/SharedJavaMainTab.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 IBM Corporation and others.
+ * Copyright (c) 2005, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
  *******************************************************************************/
 
 package org.eclipse.jdt.internal.debug.ui.launcher;
@@ -148,4 +149,17 @@
 		catch (CoreException ce) {JDIDebugUIPlugin.log(ce);}
 		fMainText.setText(mainTypeName);
 	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.jdt.debug.ui.launchConfigurations.JavaLaunchTab#initializeAttributes()
+	 * 
+	 * @since 3.9
+	 */
+	@Override
+	protected void initializeAttributes() {
+		super.initializeAttributes();
+		getAttributesLabelsForPrototype().put(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, LauncherMessages.SharedJavaMainTab_AttributeLabel_MainTypeName);
+	}
 }
diff --git a/org.eclipse.jdt.debug/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.debug/.settings/org.eclipse.jdt.core.prefs
index 5a96848..201baa5 100644
--- a/org.eclipse.jdt.debug/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jdt.debug/.settings/org.eclipse.jdt.core.prefs
@@ -220,10 +220,10 @@
 org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert

diff --git a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
index 21efd30..51a0c46 100644
--- a/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.debug; singleton:=true
-Bundle-Version: 3.11.50.qualifier
+Bundle-Version: 3.11.100.qualifier
 Bundle-ClassPath: jdi.jar,
  jdimodel.jar,
  tools.jar
@@ -41,3 +41,4 @@
 Import-Package: com.ibm.icu.text
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Eclipse-BundleShape: dir
+Automatic-Module-Name: org.eclipse.jdt.debug
diff --git a/org.eclipse.jdt.debug/forceQualifierUpdate.txt b/org.eclipse.jdt.debug/forceQualifierUpdate.txt
new file mode 100644
index 0000000..d556d7f
--- /dev/null
+++ b/org.eclipse.jdt.debug/forceQualifierUpdate.txt
@@ -0,0 +1,2 @@
+# To force a version qualifier update, add the bug here
+Bug 530709 - Comparator errors in jdt debug and jdt ui in I20180204-2000
diff --git a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/ReferenceTypeImpl.java b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/ReferenceTypeImpl.java
index 5673199..c5bff07 100644
--- a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/ReferenceTypeImpl.java
+++ b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/ReferenceTypeImpl.java
@@ -21,7 +21,6 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -356,7 +355,7 @@
 	/** The following are the stored results of JDWP calls. */
 	protected List<InterfaceType> fInterfaces = null;
 	private List<Method> fMethods = null;
-	private Hashtable<JdwpMethodID, Method> fMethodTable = null;
+	private Map<JdwpMethodID, Method> fMethodTable = null;
 	private List<Field> fFields = null;
 	private List<Method> fAllMethods = null;
 	private List<Method> fVisibleMethods = null;
@@ -522,8 +521,9 @@
 	 */
 	@Override
 	public int modifiers() {
-		if (fModifierBits != -1)
+		if (fModifierBits != -1) {
 			return fModifierBits;
+		}
 
 		initJdwpRequest();
 		try {
@@ -564,8 +564,9 @@
 	 */
 	@Override
 	public List<Method> visibleMethods() {
-		if (fVisibleMethods != null)
+		if (fVisibleMethods != null) {
 			return fVisibleMethods;
+		}
 
 		/*
 		 * Recursion: The methods of its own (own methods() command); All
@@ -596,9 +597,10 @@
 		// If it is a class, all methods of it's superclass.
 		if (this instanceof ClassType) {
 			ClassType superclass = ((ClassType) this).superclass();
-			if (superclass != null)
+			if (superclass != null) {
 				addVisibleMethods(superclass.visibleMethods(),
 						namesAndSignatures, visibleMethods);
+			}
 		}
 
 		fVisibleMethods = visibleMethods;
@@ -612,8 +614,9 @@
 	 */
 	@Override
 	public List<Method> allMethods() {
-		if (fAllMethods != null)
+		if (fAllMethods != null) {
 			return fAllMethods;
+		}
 
 		/*
 		 * Recursion: The methods of its own (own methods() command); All
@@ -637,8 +640,9 @@
 		// If it is a class, all methods of it's superclass.
 		if (this instanceof ClassType) {
 			ClassType superclass = ((ClassType) this).superclass();
-			if (superclass != null)
+			if (superclass != null) {
 				resultSet.addAll(superclass.allMethods());
+			}
 		}
 
 		fAllMethods = new ArrayList<>(resultSet);
@@ -710,8 +714,9 @@
 	 */
 	@Override
 	public List<Field> visibleFields() {
-		if (fVisibleFields != null)
+		if (fVisibleFields != null) {
 			return fVisibleFields;
+		}
 
 		/*
 		 * Recursion: The fields of its own (own fields() command); All fields
@@ -737,9 +742,10 @@
 		// If it is a class, all fields of it's superclass.
 		if (this instanceof ClassType) {
 			ClassType superclass = ((ClassType) this).superclass();
-			if (superclass != null)
+			if (superclass != null) {
 				addVisibleFields(superclass.visibleFields(), fieldNames,
 						visibleFields);
+			}
 		}
 
 		fVisibleFields = visibleFields;
@@ -753,8 +759,9 @@
 	 */
 	@Override
 	public List<Field> allFields() {
-		if (fAllFields != null)
+		if (fAllFields != null) {
 			return fAllFields;
+		}
 
 		/*
 		 * Recursion: The fields of its own (own fields() command); All fields
@@ -779,8 +786,9 @@
 		// If it is a class, all fields of it's superclass.
 		if (this instanceof ClassType) {
 			ClassType superclass = ((ClassType) this).superclass();
-			if (superclass != null)
+			if (superclass != null) {
 				resultSet.addAll(superclass.allFields());
+			}
 		}
 
 		fAllFields = new ArrayList<>(resultSet);
@@ -793,8 +801,9 @@
 	 */
 	@Override
 	public ClassLoaderReference classLoader() {
-		if (fClassLoader != null)
+		if (fClassLoader != null) {
 			return fClassLoader;
+		}
 
 		initJdwpRequest();
 		try {
@@ -818,8 +827,9 @@
 	 */
 	@Override
 	public ClassObjectReference classObject() {
-		if (fClassObject != null)
+		if (fClassObject != null) {
 			return fClassObject;
+		}
 
 		initJdwpRequest();
 		try {
@@ -898,8 +908,9 @@
 		Iterator<Field> iter = visibleFields().iterator();
 		while (iter.hasNext()) {
 			FieldImpl field = (FieldImpl) iter.next();
-			if (field.name().equals(name))
+			if (field.name().equals(name)) {
 				return field;
+			}
 		}
 		return null;
 	}
@@ -953,8 +964,9 @@
 		Iterator<Field> iter = fields().iterator();
 		while (iter.hasNext()) {
 			FieldImpl field = (FieldImpl) iter.next();
-			if (field.getFieldID().equals(fieldID))
+			if (field.getFieldID().equals(fieldID)) {
 				return field;
+			}
 		}
 		return null;
 	}
@@ -970,12 +982,14 @@
 					"", null, -1); //$NON-NLS-1$
 		}
 		if (fMethodTable == null) {
-			fMethodTable = new Hashtable<>();
+			// 509259 use temporary variable to workaround fMethodTable lazy initialization race
+			Map<JdwpMethodID, Method> methodTable = new HashMap<>();
 			Iterator<Method> iter = methods().iterator();
 			while (iter.hasNext()) {
 				MethodImpl method = (MethodImpl) iter.next();
-				fMethodTable.put(method.getMethodID(), method);
+				methodTable.put(method.getMethodID(), method);
 			}
+			fMethodTable = Collections.unmodifiableMap(methodTable);
 		}
 		return fMethodTable.get(methodID);
 	}
@@ -1020,9 +1034,10 @@
 			DataInputStream replyData = replyPacket.dataInStream();
 			HashMap<Field, Value> map = new HashMap<>();
 			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
-			if (nrOfElements != fieldsSize)
+			if (nrOfElements != fieldsSize) {
 				throw new InternalError(
 						JDIMessages.ReferenceTypeImpl_Retrieved_a_different_number_of_values_from_the_VM_than_requested_3);
+			}
 
 			for (int i = 0; i < nrOfElements; i++) {
 				map.put(fields.get(i), ValueImpl.readWithTag(this, replyData));
@@ -1066,8 +1081,9 @@
 	 */
 	@Override
 	public int compareTo(ReferenceType type) {
-		if (type == null || !type.getClass().equals(this.getClass()))
+		if (type == null || !type.getClass().equals(this.getClass())) {
 			throw new ClassCastException(JDIMessages.ReferenceTypeImpl_Can__t_compare_reference_type_to_given_object_4);
+		}
 		return name().compareTo(type.name());
 	}
 
@@ -1111,8 +1127,9 @@
 	public List<Method> methods() {
 		// Note that ArrayReference overwrites this method by returning an empty
 		// list.
-		if (fMethods != null)
+		if (fMethods != null) {
 			return fMethods;
+		}
 
 		// Note: Methods are returned in the order they occur in the class file,
 		// therefore their
@@ -1263,8 +1280,9 @@
 	@Override
 	public int getClassFileVersion() {
 		virtualMachineImpl().checkHCRSupported();
-		if (fGotClassFileVersion)
+		if (fGotClassFileVersion) {
 			return fClassFileVersion;
+		}
 
 		initJdwpRequest();
 		try {
@@ -1310,8 +1328,10 @@
 			throws IOException {
 		fReferenceTypeID.write(out);
 		if (target.fVerboseWriter != null)
+		 {
 			target.fVerboseWriter.println(
 					"referenceType", fReferenceTypeID.value()); //$NON-NLS-1$
+		}
 	}
 
 	/**
@@ -1324,7 +1344,9 @@
 				target.virtualMachineImpl());
 		ID.write(out);
 		if (target.fVerboseWriter != null)
+		 {
 			target.fVerboseWriter.println("referenceType", ID.value()); //$NON-NLS-1$
+		}
 	}
 
 	/**
@@ -2367,8 +2389,9 @@
 	 */
 	protected int optionsToJdwpOptions(int options) {
 		int jdwpOptions = 0;
-		if ((options & ClassType.INVOKE_SINGLE_THREADED) != 0)
+		if ((options & ClassType.INVOKE_SINGLE_THREADED) != 0) {
 			jdwpOptions |= MethodImpl.INVOKE_SINGLE_THREADED_JDWP;
+		}
 		return jdwpOptions;
 	}
 
@@ -2396,15 +2419,18 @@
 		MethodImpl methodImpl = (MethodImpl) method;
 
 		// Perform some checks for IllegalArgumentException.
-		if (!visibleMethods().contains(method))
+		if (!visibleMethods().contains(method)) {
 			throw new IllegalArgumentException(
 					JDIMessages.ClassTypeImpl_Class_does_not_contain_given_method_1);
-		if (method.argumentTypeNames().size() != arguments.size())
+		}
+		if (method.argumentTypeNames().size() != arguments.size()) {
 			throw new IllegalArgumentException(
 					JDIMessages.ClassTypeImpl_Number_of_arguments_doesn__t_match_2);
-		if (method.isConstructor() || method.isStaticInitializer())
+		}
+		if (method.isConstructor() || method.isStaticInitializer()) {
 			throw new IllegalArgumentException(
 					JDIMessages.ClassTypeImpl_Method_is_constructor_or_intitializer_3);
+		}
 
 		// check the type and the VM of the arguments. Convert the values if
 		// needed
@@ -2454,8 +2480,9 @@
 			ValueImpl value = ValueImpl.readWithTag(this, replyData);
 			ObjectReferenceImpl exception = ObjectReferenceImpl
 					.readObjectRefWithTag(this, replyData);
-			if (exception != null)
+			if (exception != null) {
 				throw new InvocationException(exception);
+			}
 			return value;
 		} catch (IOException e) {
 			defaultIOExceptionHandler(e);
diff --git a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/SocketTransportService.java b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/SocketTransportService.java
index f363e24..07455df 100644
--- a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/SocketTransportService.java
+++ b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/SocketTransportService.java
@@ -193,8 +193,9 @@
 		} catch (InterruptedException e1) {
 		}
 
-		if (handshakeCompleted[0])
+		if (handshakeCompleted[0]) {
 			return;
+		}
 
 		try {
 			in.close();
@@ -202,8 +203,9 @@
 		} catch (IOException e) {
 		}
 
-		if (ex[0] != null)
+		if (ex[0] != null) {
 			throw ex[0];
+		}
 
 		throw new TransportTimeoutException();
 	}
@@ -213,8 +215,9 @@
 			DataInputStream in = new DataInputStream(input);
 			byte[] handshakeInput = new byte[handshakeBytes.length];
 			in.readFully(handshakeInput);
-			if (!Arrays.equals(handshakeInput, handshakeBytes))
+			if (!Arrays.equals(handshakeInput, handshakeBytes)) {
 				throw new IOException("Received invalid handshake"); //$NON-NLS-1$
+			}
 		} catch (EOFException e) {
 			throw new ClosedConnectionException();
 		}
@@ -274,9 +277,10 @@
 	@Override
 	public ListenKey startListening(String address) throws IOException {
 		String host = null;
-		int port = 0; // jdt debugger will always specify an address in
-						// the form localhost:port
+		int port = -1;
 		if (address != null) {
+			// jdt debugger will always specify an address in
+			// the form localhost:port
 			String[] strings = address.split(":"); //$NON-NLS-1$
 			host = "localhost"; //$NON-NLS-1$
 			if (strings.length == 2) {
@@ -286,6 +290,9 @@
 				port = Integer.parseInt(strings[0]);
 			}
 		}
+		if (port == -1) {
+			throw new IOException("Unable to decode port from address: " + address); //$NON-NLS-1$
+		}
 		if (host == null) {
 			host = "localhost"; //$NON-NLS-1$
 		}
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java
index 216b9c4..299d99b 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java
@@ -65,7 +65,7 @@
 	/**
 	 * Whether this dispatcher is shutdown.
 	 */
-	private boolean fShutdown;
+	private volatile boolean fShutdown;
 	/**
 	 * Table of event listeners. Table is a mapping of <code>EventRequest</code>
 	 * to <code>IJDIEventListener</code>.
@@ -220,6 +220,50 @@
 		}
 	}
 
+	private boolean requiresExpressionEvaluation(EventSet eventSet) {
+		EventIterator iter = eventSet.eventIterator();
+		while (iter.hasNext()) {
+			Event event = iter.nextEvent();
+			if (event == null) {
+				continue;
+			}
+			IJDIEventListener listener = fEventHandlers.get(event.request());
+			if (listener instanceof IJavaLineBreakpoint) {
+				try {
+					if (((IJavaLineBreakpoint) listener).isConditionEnabled()) {
+						return true;
+					}
+				}
+				catch (CoreException e) {
+					return true; // assume the worst
+				}
+			}
+		}
+		return false;
+	}
+
+	/** @noreference public for test purposes */
+	public abstract class AbstractDispatchJob extends Job {
+		protected AbstractDispatchJob(String name) {
+			super(name);
+		}
+
+		@Override
+		public boolean belongsTo(Object family) {
+			return family == EventDispatcher.class || family == EventDispatcher.this;
+		}
+
+		@Override
+		public String toString() {
+			try {
+				return super.toString() + " for [" + fTarget.getName() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			catch (DebugException e) {
+				return super.toString();
+			}
+		}
+	}
+
 	/**
 	 * Continuously reads events that are coming from the event queue, until
 	 * this event dispatcher is shutdown. A debug target starts a thread on this
@@ -232,9 +276,9 @@
 		VirtualMachine vm = fTarget.getVM();
 		if (vm != null) {
 			EventQueue q = vm.eventQueue();
-			EventSet eventSet = null;
 			while (!isShutdown()) {
 				try {
+					EventSet eventSet;
 					try {
 						// Get the next event set.
 						eventSet = q.remove(1000);
@@ -242,42 +286,21 @@
 						break;
 					}
 
-					if (!isShutdown() && eventSet != null) {
-						final EventSet set = eventSet;
-						Job job = new Job("JDI Event Dispatch") { //$NON-NLS-1$
-							@Override
-							protected IStatus run(IProgressMonitor monitor) {
-								dispatch(set);
-								return Status.OK_STATUS;
-							}
-
-							@Override
-							public boolean belongsTo(Object family) {
-								if (family instanceof Class) {
-									Class<?> clazz = (Class<?>) family;
-									EventIterator iterator = set.eventIterator();
-									while (iterator.hasNext()) {
-										Event event = iterator.nextEvent();
-										if (clazz.isInstance(event)) {
-											return true;
-										}
-									}
+					if (eventSet != null) {
+						if (!requiresExpressionEvaluation(eventSet)) {
+							dispatch(eventSet);
+						} else {
+							// 269231 always evaluate expressions in a separate job to avoid deadlocks
+							Job job = new AbstractDispatchJob("JDI Expression Evaluation Event Dispatch") { //$NON-NLS-1$
+								@Override
+								protected IStatus run(IProgressMonitor monitor) {
+									dispatch(eventSet);
+									return Status.OK_STATUS;
 								}
-								return false;
-							}
-
-							@Override
-							public String toString() {
-								try {
-									return super.toString() + " for [" + fTarget.getName() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
-								}
-								catch (DebugException e) {
-									return super.toString();
-								}
-							}
-						};
-						job.setSystem(true);
-						job.schedule();
+							};
+							job.setSystem(true);
+							job.schedule();
+						}
 					}
 				} catch (InterruptedException e) {
 					break;
@@ -293,6 +316,7 @@
 	 */
 	public void shutdown() {
 		fShutdown = true;
+		Job.getJobManager().cancel(this);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
index 5d92208..fcef761 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
@@ -108,6 +108,14 @@
 			.getUniqueIdentifier() + ".all_instances_max_count"; //$NON-NLS-1$
 
 	/**
+	 * Boolean preference controlling if advanced sourcelookup is enabled.
+	 * 
+	 * @since 3.11
+	 */
+	public static final String PREF_ENABLE_ADVANCED_SOURCELOOKUP = JDIDebugPlugin
+			.getUniqueIdentifier() + ".enable_advanced_sourcelookup"; //$NON-NLS-1$
+
+	/**
 	 * Extension point for java logical structures.
 	 *
 	 * @since 3.1
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPluginPreferenceInitializer.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPluginPreferenceInitializer.java
index ca27983..df13b94 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPluginPreferenceInitializer.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPluginPreferenceInitializer.java
@@ -44,5 +44,6 @@
 		node.putInt(JDIDebugPlugin.PREF_ALL_INSTANCES_MAX_COUNT, 100);
 		node.putBoolean(JDIDebugModel.PREF_FILTER_BREAKPOINTS_FROM_UNRELATED_SOURCES, true);
 		node.putBoolean(JDIDebugModel.PREF_SHOW_STEP_RESULT, true);
+		node.putBoolean(JDIDebugPlugin.PREF_ENABLE_ADVANCED_SOURCELOOKUP, true);
 	}
 }
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java
index cad7552..574aab6 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,9 +22,7 @@
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.MultiStatus;
-import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.debug.core.DebugPlugin;
 import org.eclipse.debug.core.IDebugEventSetListener;
@@ -53,7 +51,6 @@
 import com.sun.jdi.event.Event;
 import com.sun.jdi.event.EventSet;
 import com.sun.jdi.event.LocatableEvent;
-import com.sun.jdi.event.ThreadStartEvent;
 import com.sun.jdi.request.ClassPrepareRequest;
 import com.sun.jdi.request.EventRequest;
 import com.sun.jdi.request.EventRequestManager;
@@ -307,13 +304,6 @@
 		ThreadReference threadRef = ((LocatableEvent) event).thread();
 		JDIThread thread = target.findThread(threadRef);
 		if (thread == null) {
-			// wait for any thread start event sets to complete processing
-			// see bug 271700
-			try {
-				Job.getJobManager().join(ThreadStartEvent.class, null);
-			} catch (OperationCanceledException e) {
-			} catch (InterruptedException e) {
-			}
 			thread = target.findThread(threadRef);
 		}
 		if (thread == null || thread.isIgnoringBreakpoints()) {
@@ -425,8 +415,9 @@
 	protected boolean installableReferenceType(ReferenceType type,
 			JDIDebugTarget target) throws CoreException {
 		String installableType = getTypeName();
-		if (installableType == null )
+		if (installableType == null ) {
 			return false;
+		}
 		String queriedType = type.name();
 		if( queriedType == null) {
 			return false;
@@ -480,10 +471,16 @@
 	protected void disableTriggerPoint(Event event) {
 		try{
 			if (isTriggerPoint() && isEnabled()) {
-					DebugPlugin.getDefault().getBreakpointManager().enableTriggerPoints(null, false);
+				if (this instanceof JavaLineBreakpoint) {
+					JavaLineBreakpoint lbp = (JavaLineBreakpoint) this;
+					if (lbp.hasCondition()) {
+						return;
+					}
+				}
+				DebugPlugin.getDefault().getBreakpointManager().enableTriggerPoints(null, false);
 					// make a note that we auto-disabled the trigger point for this breakpoint.
 					// we re enable it at cleanup of JDITarget
-				}
+			}
 			}catch (CoreException ce) {
 				JDIDebugPlugin.log(ce);
 			}
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaExceptionBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaExceptionBreakpoint.java
index b82a9e4..b355a70 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaExceptionBreakpoint.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaExceptionBreakpoint.java
@@ -32,6 +32,8 @@
 import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
 import org.eclipse.jdt.internal.debug.core.model.JDIThread;
 import org.eclipse.jdt.internal.debug.core.model.JDIValue;
+import org.eclipse.jdt.internal.debug.core.model.MethodResult;
+import org.eclipse.jdt.internal.debug.core.model.MethodResult.ResultType;
 
 import com.sun.jdi.ClassType;
 import com.sun.jdi.Location;
@@ -343,6 +345,18 @@
 	@Override
 	public boolean handleBreakpointEvent(Event event, JDIThread thread,
 			boolean suspendVote) {
+		boolean result = handleBreakpointEventInternal(event, thread, suspendVote);
+		if (!result) {
+			if (event instanceof ExceptionEvent) {
+				// about to suspend, store result
+				ExceptionEvent exceptionEvent = (ExceptionEvent) event;
+				thread.setMethodResult(new MethodResult(exceptionEvent.location().method(), -1, exceptionEvent.exception(), ResultType.throwing));
+			}
+		}
+		return result;
+	}
+
+	private boolean handleBreakpointEventInternal(Event event, JDIThread thread, boolean suspendVote) {
 		if (event instanceof ExceptionEvent) {
 			ObjectReference ex = ((ExceptionEvent) event).exception();
 			fLastTarget = thread.getJavaDebugTarget();
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaMethodBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaMethodBreakpoint.java
index 7c25d2e..ba3ea73 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaMethodBreakpoint.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaMethodBreakpoint.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,6 +28,8 @@
 import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
 import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
 import org.eclipse.jdt.internal.debug.core.model.JDIThread;
+import org.eclipse.jdt.internal.debug.core.model.MethodResult;
+import org.eclipse.jdt.internal.debug.core.model.MethodResult.ResultType;
 
 import com.sun.jdi.ClassType;
 import com.sun.jdi.Location;
@@ -438,8 +440,13 @@
 			MethodExitEvent exitEvent = (MethodExitEvent) event;
 			fLastEventTypes.put(thread.getDebugTarget(), EXIT_EVENT);
 			//inActivateTriggerPoint(event);
-			return handleMethodEvent(exitEvent, exitEvent.method(), thread,
+			boolean result = handleMethodEvent(exitEvent, exitEvent.method(), thread,
 					suspendVote);
+			if (!result) {
+				// about to suspend, store result
+				thread.setMethodResult(new MethodResult(exitEvent.method(), -1, exitEvent.returnValue(), ResultType.returning));
+			}
+			return result;
 		} else if (event instanceof BreakpointEvent) {
 			fLastEventTypes.put(thread.getDebugTarget(), ENTRY_EVENT);
 			return super.handleBreakpointEvent(event, thread, suspendVote);
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java
index ef7576a..040360f 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/hcr/JavaHotCodeReplaceManager.java
@@ -331,39 +331,6 @@
 	}
 
 	/**
-	 * Filters elements out of the given collections of resources and qualified
-	 * names if there is no type corresponding type loaded in the given debug
-	 * target. This method allows us to avoid bogus HCR attempts and
-	 * "HCR failed" notifications.
-	 *
-	 * @param target
-	 *            the debug target
-	 * @param resources
-	 *            the list of resources to filter
-	 * @param qualifiedNames
-	 *            the list of qualified names to filter, which corresponds to
-	 *            the list of resources on a one-to-one-basis
-	 */
-	private void filterUnloadedTypes(JDIDebugTarget target, List<IResource> resources,
-			List<String> qualifiedNames) {
-		for (int i = 0, numElements = qualifiedNames.size(); i < numElements; i++) {
-			String name = qualifiedNames.get(i);
-			List<ReferenceType> list = target.jdiClassesByName(name);
-			if (list.isEmpty()) {
-				// If no classes with the given name are loaded in the VM, don't
-				// waste
-				// cycles trying to replace.
-				qualifiedNames.remove(i);
-				resources.remove(i);
-				// Decrement the index and number of elements to compensate for
-				// item removal
-				i--;
-				numElements--;
-			}
-		}
-	}
-
-	/**
 	 * Notify the given targets that HCR failed for classes with the given fully
 	 * qualified names.
 	 */
@@ -379,8 +346,7 @@
 				// unloaded types on a per-target basis.
 				List<IResource> resourcesToReplace = new ArrayList<>(resources);
 				List<String> qualifiedNamesToReplace = new ArrayList<>(qualifiedNames);
-				filterUnloadedTypes(target, resourcesToReplace,
-						qualifiedNamesToReplace);
+				target.filterNotLoadedTypes(resourcesToReplace, qualifiedNamesToReplace);
 
 				if (!qualifiedNamesToReplace.isEmpty()) {
 					// Don't notify if the changed types aren't loaded.
@@ -471,13 +437,13 @@
 			List<String> qualifiedNamesToReplace = new ArrayList<>(qualifiedNames);
 
 			// Make sure we only try to replace types from related projects
-			filterUnrelatedResources(target, resourcesToReplace, qualifiedNamesToReplace);
+			target.filterUnrelatedResources(resourcesToReplace, qualifiedNamesToReplace);
 			if (qualifiedNamesToReplace.isEmpty()) {
 				// If none of the changed types are related to our target, do nothing.
 				continue;
 			}
 
-			filterUnloadedTypes(target, resourcesToReplace, qualifiedNamesToReplace);
+			target.filterNotLoadedTypes(resourcesToReplace, qualifiedNamesToReplace);
 			if (qualifiedNamesToReplace.isEmpty()) {
 				// If none of the changed types are loaded, do nothing.
 				continue;
@@ -548,18 +514,6 @@
 		fDeltaCache.clear();
 	}
 
-	private void filterUnrelatedResources(JDIDebugTarget target, List<IResource> resourcesToReplace, List<String> qualifiedNamesToReplace) {
-		Iterator<IResource> resources = resourcesToReplace.iterator();
-		Iterator<String> names = qualifiedNamesToReplace.iterator();
-		while (resources.hasNext()) {
-			boolean supported = target.supportsResource(() -> names.next(), resources.next());
-			if (!supported) {
-				resources.remove();
-				names.remove();
-			}
-		}
-	}
-
 	/**
 	 * Returns whether the given exception, which occurred during HCR, should be
 	 * logged. We anticipate that we can get IncompatibleThreadStateExceptions
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.java
index 67040ba..7f1c9c7 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -124,7 +124,9 @@
 	public static String JDIStackFrame_pop_frame_not_supported;
 	public static String JDIStackFrame_Variable_information_unavailable_for_native_methods;
 	public static String JDIStackFrame_ReturnValue;
+	public static String JDIStackFrame_ReturningValue;
 	public static String JDIStackFrame_ExceptionThrown;
+	public static String JDIStackFrame_ThrowingException;
 	public static String JDIStackFrame_NoMethodReturnValue;
 
 	public static String JDIThisVariable_exception_while_retrieving_type_this;
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.properties b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.properties
index 3b8f5f6..fcf0b5d 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.properties
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugModelMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2016 IBM Corporation and others.
+# Copyright (c) 2000, 2017 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -92,7 +92,9 @@
 JDIStackFrame_pop_frame_not_supported=Popping frames not supported.
 JDIStackFrame_Variable_information_unavailable_for_native_methods=Variable information unavailable for native methods
 JDIStackFrame_ReturnValue={0}() returned
+JDIStackFrame_ReturningValue={0}() is returning
 JDIStackFrame_ExceptionThrown={0}() threw
+JDIStackFrame_ThrowingException={0}() is throwing
 JDIStackFrame_NoMethodReturnValue=no method return value
 
 JDIThisVariable_exception_while_retrieving_type_this={0} occurred while retrieving type ''this''.
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java
index f76bac1..320cefa 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java
@@ -2440,13 +2440,6 @@
 			ThreadReference ref = ((ThreadDeathEvent) event).thread();
 			JDIThread thread = findThread(ref);
 			if (thread == null) {
-				// wait for any thread start event sets to complete processing
-				// see bug 272494
-				try {
-					Job.getJobManager().join(ThreadStartEvent.class, null);
-				} catch (OperationCanceledException e) {
-				} catch (InterruptedException e) {
-				}
 				thread = target.findThread(ref);
 			}
 			if (thread != null) {
@@ -3339,4 +3332,51 @@
 	public ListenerList<IJavaHotCodeReplaceListener> getHotCodeReplaceListeners() {
 		return fHCRListeners;
 	}
+
+	/**
+	 * Filters elements out of the given collections of resources and qualified names if there is no related resources in the given debug target. This
+	 * method allows us to avoid bogus HCR attempts and "HCR failed" notifications.
+	 *
+	 * @param resourcesToFilter
+	 *            the list of resources to filter
+	 * @param qualifiedNamesToFilter
+	 *            the list of qualified names to filter, which corresponds to the list of resources on a one-to-one-basis
+	 */
+	public void filterUnrelatedResources(List<IResource> resourcesToFilter, List<String> qualifiedNamesToFilter) {
+		Iterator<IResource> resources = resourcesToFilter.iterator();
+		Iterator<String> names = qualifiedNamesToFilter.iterator();
+		while (resources.hasNext()) {
+			boolean supported = supportsResource(() -> names.next(), resources.next());
+			if (!supported) {
+				resources.remove();
+				names.remove();
+			}
+		}
+	}
+
+	/**
+	 * Filters elements out of the given collections of resources and qualified names if there is no type corresponding type loaded in the given debug
+	 * target. This method allows us to avoid bogus HCR attempts and "HCR failed" notifications.
+	 *
+	 * @param resources
+	 *            the list of resources to filter
+	 * @param qualifiedNames
+	 *            the list of qualified names to filter, which corresponds to the list of resources on a one-to-one-basis
+	 */
+	public void filterNotLoadedTypes(List<IResource> resources, List<String> qualifiedNames) {
+		for (int i = 0, numElements = qualifiedNames.size(); i < numElements; i++) {
+			String name = qualifiedNames.get(i);
+			List<ReferenceType> list = jdiClassesByName(name);
+			if (list.isEmpty()) {
+				// If no classes with the given name are loaded in the VM, don't
+				// waste cycles trying to replace.
+				qualifiedNames.remove(i);
+				resources.remove(i);
+				// Decrement the index and number of elements to compensate for
+				// item removal
+				i--;
+				numElements--;
+			}
+		}
+	}
 }
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java
index 73235e0..01e8e16 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIStackFrame.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -20,7 +20,6 @@
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
-
 import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.model.IRegisterGroup;
@@ -30,12 +29,9 @@
 import org.eclipse.debug.core.model.ITerminate;
 import org.eclipse.debug.core.model.IThread;
 import org.eclipse.debug.core.model.IVariable;
-
 import org.eclipse.jdi.internal.ValueImpl;
 import org.eclipse.jdi.internal.VirtualMachineImpl;
-
 import org.eclipse.jdt.core.Signature;
-
 import org.eclipse.jdt.debug.core.IJavaClassType;
 import org.eclipse.jdt.debug.core.IJavaModifiers;
 import org.eclipse.jdt.debug.core.IJavaObject;
@@ -44,9 +40,9 @@
 import org.eclipse.jdt.debug.core.IJavaThread;
 import org.eclipse.jdt.debug.core.IJavaValue;
 import org.eclipse.jdt.debug.core.IJavaVariable;
-
 import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
 import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIReturnValueVariable;
+import org.eclipse.jdt.internal.debug.core.model.MethodResult.ResultType;
 
 import com.ibm.icu.text.MessageFormat;
 import com.sun.jdi.AbsentInformationException;
@@ -384,22 +380,28 @@
 	 */
 	private void addStepReturnValue(List<IJavaVariable> variables) {
 		if (fIsTop) {
-			StepResult stepResult = fThread.fStepResult;
-			if (stepResult != null) {
-				if (stepResult.fIsReturnValue) {
-					if (fDepth + 1 != stepResult.fTargetFrameCount) {
+			MethodResult methodResult = fThread.getMethodResult();
+			if (methodResult != null) {
+				if (methodResult.fResultType == ResultType.returned) {
+					if (fDepth + 1 != methodResult.fTargetFrameCount) {
 						// can happen e.g., because of checkPackageAccess/System.getSecurityManager()
 						return;
 					}
-					String name = MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_ReturnValue, stepResult.fMethod.name());
-					variables.add(0, new JDIReturnValueVariable(name, JDIValue.createValue(getJavaDebugTarget(), stepResult.fValue), true));
-				} else {
-					if (fDepth + 1 > stepResult.fTargetFrameCount) {
+					String name = MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_ReturnValue, methodResult.fMethod.name());
+					variables.add(0, new JDIReturnValueVariable(name, JDIValue.createValue(getJavaDebugTarget(), methodResult.fValue), true));
+				} else if (methodResult.fResultType == ResultType.returning) {
+					String name = MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_ReturningValue, methodResult.fMethod.name());
+					variables.add(0, new JDIReturnValueVariable(name, JDIValue.createValue(getJavaDebugTarget(), methodResult.fValue), true));
+				} else if (methodResult.fResultType == ResultType.threw) {
+					if (fDepth + 1 > methodResult.fTargetFrameCount) {
 						// don't know if this really can happen, but other jvm suprises were not expected either
 						return;
 					}
-					String name = MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_ExceptionThrown, stepResult.fMethod.name());
-					variables.add(0, new JDIReturnValueVariable(name, JDIValue.createValue(getJavaDebugTarget(), stepResult.fValue), true));
+					String name = MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_ExceptionThrown, methodResult.fMethod.name());
+					variables.add(0, new JDIReturnValueVariable(name, JDIValue.createValue(getJavaDebugTarget(), methodResult.fValue), true));
+				} else if (methodResult.fResultType == ResultType.throwing) {
+					String name = MessageFormat.format(JDIDebugModelMessages.JDIStackFrame_ThrowingException, methodResult.fMethod.name());
+					variables.add(0, new JDIReturnValueVariable(name, JDIValue.createValue(getJavaDebugTarget(), methodResult.fValue), true));
 				}
 			} else if(JDIThread.showStepResultIsEnabled()) {
 				variables.add(0, new JDIReturnValueVariable(JDIDebugModelMessages.JDIStackFrame_NoMethodReturnValue, new JDIPlaceholderValue(getJavaDebugTarget(), ""), false)); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java
index b8de172..01e85ab 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -55,6 +55,7 @@
 import org.eclipse.jdt.internal.debug.core.breakpoints.ConditionalBreakpointHandler;
 import org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint;
 import org.eclipse.jdt.internal.debug.core.breakpoints.JavaLineBreakpoint;
+import org.eclipse.jdt.internal.debug.core.model.MethodResult.ResultType;
 
 import com.ibm.icu.text.MessageFormat;
 import com.sun.jdi.BooleanValue;
@@ -290,9 +291,12 @@
 	 */
 	private int fStepReturnTargetFrameCount;
 
-	private StepResult fStepResultCandidate;
+	private MethodResult fStepResultCandidate;
 
-	StepResult fStepResult;
+	/**
+	 * Result of the last step step-over or step-return operation or method exit breakpoint of exception break point
+	 */
+	private MethodResult fMethodResult;
 
 	/**
 	 * Creates a new thread on the underlying thread reference in the given
@@ -1469,6 +1473,9 @@
 						return true;
 					}
 				}
+				DebugPlugin.getDefault().getBreakpointManager().enableTriggerPoints(null, false);
+					// make a note that we auto-disabled the trigger point for this breakpoint.
+					// we re enable it at cleanup of JDITarget
 			}
 		}
 
@@ -1697,7 +1704,7 @@
 		}
 		try {
 			setRunning(true);
-			clearStepReturnResult();
+			clearMethodResult();
 			if (fireNotification) {
 				fireResumeEvent(DebugEvent.CLIENT_REQUEST);
 			}
@@ -1728,8 +1735,8 @@
 		}
 	}
 
-	private void clearStepReturnResult() {
-		fStepResult = null;
+	private void clearMethodResult() {
+		setMethodResult(null);
 	}
 
 	/**
@@ -2069,7 +2076,7 @@
 	protected synchronized void resumedByVM() throws DebugException {
 		fClientSuspendRequest = false;
 		setRunning(true);
-		clearStepReturnResult();
+		clearMethodResult();
 		preserveStackFrames();
 		// This method is called *before* the VM is actually resumed.
 		// To ensure that all threads will fully resume when the VM
@@ -2444,7 +2451,7 @@
 				setPendingStepHandler(this);
 				addJDIEventListener(this, getStepRequest());
 				setRunning(true);
-				clearStepReturnResult();
+				clearMethodResult();
 				preserveStackFrames();
 				fireResumeEvent(getStepDetail());
 				invokeThread();
@@ -2573,7 +2580,12 @@
 						methodExitRequest.addClassFilter(currentFrame.location().declaringType());
 
 						if (manager.virtualMachine().canUseInstanceFilters()) {
-							ObjectReference thisObject = currentFrame.thisObject();
+							ObjectReference thisObject = null;
+							try {
+								thisObject = currentFrame.thisObject();
+							} catch (Exception e) {
+								// ignore errors here, continue without filtering
+							}
 							if (thisObject != null) {
 								methodExitRequest.addInstanceFilter(thisObject);
 							}
@@ -2585,7 +2597,7 @@
 						fStepReturnTargetFrameCount = frameCount - 1; // depth of the frame that is returned to
 						addJDIEventListener(this, methodExitRequest);
 
-						ExceptionRequest exceptionRequest = manager.createExceptionRequest(null, true, true);
+						ExceptionRequest exceptionRequest = manager.createExceptionRequest(null, true, false);
 						exceptionRequest.addThreadFilter(fThread);
 						exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
 						exceptionRequest.enable();
@@ -2714,9 +2726,7 @@
 
 			if (applyStepFilters() && isStepFiltersEnabled()) {
 				Location currentLocation = getOriginalStepLocation();
-				if (currentLocation == null
-						|| !JAVA_STRATUM_CONSTANT.equals(currentLocation
-								.declaringType().defaultStratum())) {
+				if (!isSupported(currentLocation)) {
 					return;
 				}
 				// Removed the fix for bug 5587, to address bug 41510
@@ -2770,14 +2780,14 @@
 					if (stepResultMethod != null) {
 						MethodExitEvent methodExitEvent = (MethodExitEvent) event;
 						if (methodExitEvent.location().method().equals(stepResultMethod)) {
-							fStepResultCandidate = new StepResult(fStepResultMethod, fStepReturnTargetFrameCount, methodExitEvent.returnValue(), true);
+							fStepResultCandidate = new MethodResult(fStepResultMethod, fStepReturnTargetFrameCount, methodExitEvent.returnValue(), ResultType.returned);
 						}
 						return true;
 					}
 				}
 				if (event instanceof ExceptionEvent) {
 					ExceptionEvent exceptionEvent = (ExceptionEvent) event;
-					fStepResultCandidate = new StepResult(fStepResultMethod, fStepReturnTargetFrameCount, exceptionEvent.exception(), false);
+					fStepResultCandidate = new MethodResult(fStepResultMethod, fStepReturnTargetFrameCount, exceptionEvent.exception(), ResultType.threw);
 					return true;
 				}
 				if (event instanceof MethodEntryEvent) {
@@ -2795,7 +2805,7 @@
 				Location currentLocation = stepEvent.location();
 
 				if (fStepResultCandidate != null) {
-					fStepResult = fStepResultCandidate;
+					setMethodResult(fStepResultCandidate);
 					fStepResultMethod = null;
 					fStepReturnTargetFrameCount = -1;
 					fStepResultCandidate = null;
@@ -2842,7 +2852,7 @@
 					setRunning(true);
 					deleteStepRequest();
 					createSecondaryStepRequest();
-					clearStepReturnResult();
+					clearMethodResult();
 					return true;
 					// otherwise, we're done stepping
 				}
@@ -3185,7 +3195,7 @@
 				setRunning(true);
 				deleteStepRequest();
 				createSecondaryStepRequest();
-				clearStepReturnResult();
+				clearMethodResult();
 				return true;
 			} catch (DebugException e) {
 				logError(e);
@@ -3734,4 +3744,19 @@
 		return Platform.getPreferencesService().getBoolean(JDIDebugPlugin.getUniqueIdentifier(), JDIDebugModel.PREF_SHOW_STEP_RESULT, true, null);
 	}
 
+	protected boolean isSupported(Location currentLocation) {
+		if (currentLocation == null) {
+			return false;
+		}
+		return JAVA_STRATUM_CONSTANT.equals(currentLocation.declaringType().defaultStratum());
+	}
+
+	public MethodResult getMethodResult() {
+		return fMethodResult;
+	}
+
+	public void setMethodResult(MethodResult fMethodResult) {
+		this.fMethodResult = fMethodResult;
+	}
+
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/MethodResult.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/MethodResult.java
new file mode 100644
index 0000000..0312188
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/MethodResult.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 Till Brychcy and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Till Brychcy - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.debug.core.model;
+
+import com.sun.jdi.Method;
+import com.sun.jdi.Value;
+
+public class MethodResult {
+	public enum ResultType {
+		/** fValue is returned value after a step operation */
+		returned,
+
+		/** fValue is exception thrown after a step operation */
+		threw,
+
+		/** fValue is value being returned at a method exit breakpoint */
+		returning,
+
+		/** fValue is exception being thrown in a exception breakpoint */
+		throwing
+	}
+
+	public MethodResult(Method method, int targetFrameCount, Value value, ResultType resultType) {
+		this.fMethod = method;
+		this.fTargetFrameCount = targetFrameCount;
+		this.fValue = value;
+		this.fResultType = resultType;
+	}
+
+	/**
+	 * The method from which {@link #fValue} originates
+	 */
+	public final Method fMethod;
+
+	/**
+	 * If a step-return or step-over is in progress, this is the stack size at which the result value is expected. Otherwise ignored.
+	 */
+	public final int fTargetFrameCount;
+
+	/**
+	 * Return value or exception
+	 */
+	public final Value fValue;
+
+	/**
+	 * Whether {@link #fValue} was returned or thrown
+	 */
+	public final ResultType fResultType;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/StepResult.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/StepResult.java
deleted file mode 100644
index 54a7c17..0000000
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/StepResult.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Till Brychcy and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Till Brychcy - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.jdt.internal.debug.core.model;
-
-import com.sun.jdi.Method;
-import com.sun.jdi.Value;
-
-public class StepResult {
-
-	public StepResult(Method method, int targetFrameCount, Value value, boolean isReturnValue) {
-		this.fMethod = method;
-		this.fTargetFrameCount = targetFrameCount;
-		this.fValue = value;
-		this.fIsReturnValue = isReturnValue;
-	}
-
-	/**
-	 * The method that was being stepped-over or step-returned from.
-	 */
-	public final Method fMethod;
-
-	/**
-	 * If a step-return or step-over is in progress, this is the stack size at which the result value is expected.
-	 */
-	public final int fTargetFrameCount;
-
-	/**
-	 * Returned value or thrown exception after a step-return or step-over.
-	 */
-	public final Value fValue;
-
-	/**
-	 * Whether {@link #fValue} was returned or thrown
-	 */
-	public final boolean fIsReturnValue;
-}
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug/pom.xml b/org.eclipse.jdt.debug/pom.xml
index 17281bb..9bf96d8 100644
--- a/org.eclipse.jdt.debug/pom.xml
+++ b/org.eclipse.jdt.debug/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  Copyright (c) 2012, 2016 Eclipse Foundation and others.
+  Copyright (c) 2012, 2017 Eclipse Foundation and others.
   All rights reserved. This program and the accompanying materials
   are made available under the terms of the Eclipse Distribution License v1.0
   which accompanies this distribution, and is available at
@@ -14,10 +14,10 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.3-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.debug</artifactId>
-  <version>3.11.50-SNAPSHOT</version>
+  <version>3.11.100-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/org.eclipse.jdt.launching.javaagent/.classpath b/org.eclipse.jdt.launching.javaagent/.classpath
new file mode 100644
index 0000000..d1cc5bb
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.launching.javaagent/.project b/org.eclipse.jdt.launching.javaagent/.project
new file mode 100644
index 0000000..173d0dc
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/.project
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.jdt.launching.javaagent</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.launching.javaagent/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.launching.javaagent/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..50e7022
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,414 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=error
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=ignore
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=error
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=error
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=error
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=error
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL,HIGH,HIGH
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,EXPERIMENTAL,CONTEXTLAUNCHING
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=0
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=0
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=150
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=150
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/org.eclipse.jdt.launching.javaagent/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jdt.launching.javaagent/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..666d89f
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,109 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_Platform Debug Cleanups
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_Platform Debug Formatting
+formatter_settings_version=12
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.jdt.launching.javaagent/META-INF/MANIFEST.MF b/org.eclipse.jdt.launching.javaagent/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8cafc1d
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.jdt.launching.javaagent;singleton:=true
+Bundle-Version: 3.9.0.qualifier
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.objectweb.asm;bundle-version="[6.0.0,7.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: org.eclipse.jdt.launching.javaagent
diff --git a/org.eclipse.jdt.launching.javaagent/pom.xml b/org.eclipse.jdt.launching.javaagent/pom.xml
new file mode 100644
index 0000000..de705cd
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/pom.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2011-2016 Igor Fedorenko
+  All rights reserved. This program and the accompanying materials
+  are made available under the terms of the Eclipse Public License v1.0
+  which accompanies this distribution, and is available at
+  http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.eclipse.jdt</groupId>
+  <artifactId>org.eclipse.jdt.launching.javaagent</artifactId>
+  <version>3.9.0-SNAPSHOT</version>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm</artifactId>
+      <version>6.0</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.5.1</version>
+        <configuration>
+          <!-- http://maven.apache.org/plugins/maven-compiler-plugin/ -->
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>3.0.2</version>
+        <configuration>
+          <archive>
+            <manifestEntries>
+              <Premain-Class>org.eclipse.jdt.launching.internal.javaagent.Premain</Premain-Class>
+            </manifestEntries>
+          </archive>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>3.1.0</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <createSourcesJar>true</createSourcesJar>
+              <relocations>
+                <relocation>
+                  <!--
+                    | javaagent classes are added to application classpath
+                    | relocate ASM to our internal package to avoid possible conflicts 
+                    -->
+                  <pattern>org.objectweb.asm</pattern>
+                  <shadedPattern>org.eclipse.jdt.launching.internal.org.objectweb.asm</shadedPattern>
+                </relocation>
+              </relocations>
+              <finalName>javaagent-shaded</finalName>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/org.eclipse.jdt.launching.javaagent/src/main/java/org/eclipse/jdt/launching/internal/javaagent/Premain.java b/org.eclipse.jdt.launching.javaagent/src/main/java/org/eclipse/jdt/launching/internal/javaagent/Premain.java
new file mode 100644
index 0000000..e286992
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/src/main/java/org/eclipse/jdt/launching/internal/javaagent/Premain.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.launching.internal.javaagent;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.net.URL;
+import java.security.CodeSource;
+import java.security.ProtectionDomain;
+
+import org.eclipse.jdt.launching.internal.weaving.ClassfileTransformer;
+
+public class Premain {
+	private static final ClassfileTransformer transformer = new ClassfileTransformer();
+
+	public static void premain(@SuppressWarnings("unused") String agentArgs, Instrumentation inst) {
+		// System.err.println("Advanced source lookup support loaded."); //$NON-NLS-1$
+
+		inst.addTransformer(new ClassFileTransformer() {
+			public byte[] transform(ClassLoader loader, final String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+				try {
+					if (protectionDomain == null) {
+						return null;
+					}
+
+					if (className == null) {
+						return null;
+					}
+
+					final CodeSource codeSource = protectionDomain.getCodeSource();
+					if (codeSource == null) {
+						return null;
+					}
+
+					final URL locationUrl = codeSource.getLocation();
+					if (locationUrl == null) {
+						return null;
+					}
+
+					final String location = locationUrl.toExternalForm();
+
+					return transformer.transform(classfileBuffer, location);
+				}
+				catch (Exception e) {
+					System.err.print("Could not instrument class " + className + ": "); //$NON-NLS-1$ //$NON-NLS-2$
+					e.printStackTrace(System.err);
+				}
+				return null;
+			}
+		});
+	}
+}
diff --git a/org.eclipse.jdt.launching.javaagent/src/main/java/org/eclipse/jdt/launching/internal/weaving/ClassfileTransformer.java b/org.eclipse.jdt.launching.javaagent/src/main/java/org/eclipse/jdt/launching/internal/weaving/ClassfileTransformer.java
new file mode 100644
index 0000000..a8cda8a
--- /dev/null
+++ b/org.eclipse.jdt.launching.javaagent/src/main/java/org/eclipse/jdt/launching/internal/weaving/ClassfileTransformer.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.launching.internal.weaving;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+
+public class ClassfileTransformer {
+
+	// must match JDIHelpers.STRATA_ID
+	private static final String STRATA_ID = "jdt"; //$NON-NLS-1$
+
+	public byte[] transform(byte[] classfileBuffer, final String location) {
+
+		final ClassReader r = new ClassReader(classfileBuffer, 0, classfileBuffer.length);
+		final ClassWriter w = new ClassWriter(0);
+
+		r.accept(new ClassVisitor(Opcodes.ASM5, w) {
+			@Override
+			public void visitSource(String source, String debug) {
+				String javaSource = source;
+				// TODO merge SMAP if present (always present when used together with Equinox weaver)
+				if (debug == null) {
+					StringBuilder smap = new StringBuilder();
+					smap.append("SMAP\n"); //$NON-NLS-1$
+					smap.append(javaSource).append("\n"); //$NON-NLS-1$
+					// default strata name
+					smap.append("Java\n"); //$NON-NLS-1$
+					smap.append("*S " + STRATA_ID + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+					smap.append("*F\n"); //$NON-NLS-1$
+					smap.append("1 ").append(source).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+					smap.append("2 ").append(location).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+					// JSR-045, StratumSection
+					// "One FileSection and one LineSection (in either order) must follow the StratumSection"
+					smap.append("*L\n"); //$NON-NLS-1$
+					smap.append("*E\n"); //$NON-NLS-1$
+					debug = smap.toString();
+				}
+
+				super.visitSource(javaSource, debug);
+			}
+		}, 0);
+
+		return w.toByteArray();
+	}
+}
diff --git a/org.eclipse.jdt.launching.macosx/META-INF/MANIFEST.MF b/org.eclipse.jdt.launching.macosx/META-INF/MANIFEST.MF
index c5a8abf..3a1794b 100644
--- a/org.eclipse.jdt.launching.macosx/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.launching.macosx/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.launching.macosx; singleton:=true
-Bundle-Version: 3.4.0.qualifier
+Bundle-Version: 3.4.100.qualifier
 Bundle-Activator: org.eclipse.jdt.internal.launching.macosx.MacOSXLaunchingPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -16,3 +16,4 @@
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-ActivationPolicy: lazy
 Export-Package: org.eclipse.jdt.internal.launching.macosx;x-internal:=true
+Automatic-Module-Name: org.eclipse.jdt.launching.macosx
diff --git a/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstall.java b/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstall.java
index df8d459..1f80965 100644
--- a/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstall.java
+++ b/org.eclipse.jdt.launching.macosx/macosx/org/eclipse/jdt/internal/launching/macosx/MacOSXVMInstall.java
@@ -13,10 +13,13 @@
 import java.io.File;
 
 import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jdt.internal.launching.LaunchingMessages;
+import org.eclipse.jdt.internal.launching.LaunchingPlugin;
 import org.eclipse.jdt.internal.launching.StandardVMType;
 import org.eclipse.jdt.launching.AbstractVMInstall;
 import org.eclipse.jdt.launching.IVMInstallType;
 import org.eclipse.jdt.launching.IVMRunner;
+import org.eclipse.osgi.util.NLS;
 
 public class MacOSXVMInstall extends AbstractVMInstall {
 
@@ -26,11 +29,13 @@
 
 	@Override
 	public IVMRunner getVMRunner(String mode) {
-		if (ILaunchManager.RUN_MODE.equals(mode))
+		if (ILaunchManager.RUN_MODE.equals(mode)) {
 			return new MacOSXVMRunner(this);
+		}
 		
-		if (ILaunchManager.DEBUG_MODE.equals(mode))
+		if (ILaunchManager.DEBUG_MODE.equals(mode)) {
 			return new MacOSXDebugVMRunner(this);
+		}
 		
 		return null;
 	}
@@ -41,7 +46,7 @@
         if (installLocation != null) {
             File executable= StandardVMType.findJavaExecutable(installLocation);
             if (executable != null) {
-                MacOSXVMInstallType installType= (MacOSXVMInstallType) getVMInstallType();        
+                MacOSXVMInstallType installType= (MacOSXVMInstallType) getVMInstallType();
                 String vmVersion= installType.getVMVersion(installLocation, executable);
                 // strip off extra info
                 StringBuffer version= new StringBuffer();
@@ -57,6 +62,7 @@
                     return version.toString();
                 }
             }
+			LaunchingPlugin.log(NLS.bind(LaunchingMessages.vmInstall_could_not_determine_java_Version, installLocation.getAbsolutePath()));
         }
         return null;
     }
diff --git a/org.eclipse.jdt.launching.macosx/pom.xml b/org.eclipse.jdt.launching.macosx/pom.xml
index 5408310..379d330 100644
--- a/org.eclipse.jdt.launching.macosx/pom.xml
+++ b/org.eclipse.jdt.launching.macosx/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  Copyright (c) 2012, 2016 Eclipse Foundation and others.
+  Copyright (c) 2012, 2017 Eclipse Foundation and others.
   All rights reserved. This program and the accompanying materials
   are made available under the terms of the Eclipse Distribution License v1.0
   which accompanies this distribution, and is available at
@@ -14,11 +14,11 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.3-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.launching.macosx</artifactId>
-  <version>3.4.0-SNAPSHOT</version>
+  <version>3.4.100-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
   <build>
diff --git a/org.eclipse.jdt.launching.ui.macosx/META-INF/MANIFEST.MF b/org.eclipse.jdt.launching.ui.macosx/META-INF/MANIFEST.MF
index e6a1997..1a347f4 100644
--- a/org.eclipse.jdt.launching.ui.macosx/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.launching.ui.macosx/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.launching.ui.macosx;singleton:=true
-Bundle-Version: 1.2.0.qualifier
+Bundle-Version: 1.2.100.qualifier
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-Vendor: %providerName
@@ -16,3 +16,4 @@
 Bundle-Activator: org.eclipse.jdt.internal.ui.macbundler.MacOSXUILaunchingPlugin
 Bundle-ActivationPolicy: lazy
 Export-Package: org.eclipse.jdt.internal.ui.macbundler;x-internal:=true
+Automatic-Module-Name: org.eclipse.jdt.launching.ui.macosx
diff --git a/org.eclipse.jdt.launching.ui.macosx/pom.xml b/org.eclipse.jdt.launching.ui.macosx/pom.xml
index 9f3f0f3..fabbffa 100644
--- a/org.eclipse.jdt.launching.ui.macosx/pom.xml
+++ b/org.eclipse.jdt.launching.ui.macosx/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  Copyright (c) 2012, 2016 Eclipse Foundation and others.
+  Copyright (c) 2012, 2017 Eclipse Foundation and others.
   All rights reserved. This program and the accompanying materials
   are made available under the terms of the Eclipse Distribution License v1.0
   which accompanies this distribution, and is available at
@@ -14,11 +14,11 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.3-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.launching.ui.macosx</artifactId>
-  <version>1.2.0-SNAPSHOT</version>
+  <version>1.2.100-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
   <build>
diff --git a/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage1.java b/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage1.java
index 77d876b..4e24d01 100644
--- a/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage1.java
+++ b/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage1.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -38,23 +38,21 @@
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
 
-
 public class BundleWizardPage1 extends BundleWizardBasePage {
-	
-	static String[] JVMS= {
-		"1.3+",	//$NON-NLS-1$
-		"1.3*",	//$NON-NLS-1$
-		"1.4.2",	//$NON-NLS-1$
-		"1.4+",	//$NON-NLS-1$
-		"1.4*",	//$NON-NLS-1$
-		"1.5+",	//$NON-NLS-1$
-		"1.5*",	//$NON-NLS-1$
-		"1.6+",	//$NON-NLS-1$
-		"1.6*"	//$NON-NLS-1$
+
+	static String[] JVMS = { "1.3+", //$NON-NLS-1$
+			"1.3*", //$NON-NLS-1$
+			"1.4.2", //$NON-NLS-1$
+			"1.4+", //$NON-NLS-1$
+			"1.4*", //$NON-NLS-1$
+			"1.5+", //$NON-NLS-1$
+			"1.5*", //$NON-NLS-1$
+			"1.6+", //$NON-NLS-1$
+			"1.6*" //$NON-NLS-1$
 	};
 
-	ILaunchConfiguration[] fConfigurations= new ILaunchConfiguration[0];
-	Combo fLocation;	
+	ILaunchConfiguration[] fConfigurations = new ILaunchConfiguration[0];
+	Combo fLocation;
 	Combo fLaunchConfigs;
 	Combo fJVMVersion;
 	Text fAppName;
@@ -62,167 +60,161 @@
 	Text fArguments;
 	Text fIconFileName;
 	Button fUseSWT;
-	
-	
+
 	public BundleWizardPage1(BundleDescription bd) {
 		super("page1", bd); //$NON-NLS-1$
 	}
 
 	@Override
 	public void createContents(Composite c) {
-		
-		final Shell shell= c.getShell();
-				
-		Composite c1= createComposite(c, 2);
-			createLabel(c1, Util.getString("page1.launchConfig.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-		
-			fLaunchConfigs= new Combo(c1, SWT.READ_ONLY);
-			fillCombo(fLaunchConfigs);
-			fLaunchConfigs.addSelectionListener(
-				new SelectionAdapter() {
-					@Override
-					public void widgetSelected(SelectionEvent e) {
-						int ix= fLaunchConfigs.getSelectionIndex();
-						if (ix > 0 && ix < fConfigurations.length) {
-							fBundleDescription.clear();
-							fBundleDescription.inititialize(fConfigurations[ix]);
-						}
-					}
+
+		final Shell shell = c.getShell();
+
+		Composite c1 = createComposite(c, 2);
+		createLabel(c1, Util.getString("page1.launchConfig.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+
+		fLaunchConfigs = new Combo(c1, SWT.READ_ONLY);
+		fillCombo(fLaunchConfigs);
+		fLaunchConfigs.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				int ix = fLaunchConfigs.getSelectionIndex();
+				if (ix > 0 && ix < fConfigurations.length) {
+					fBundleDescription.clear();
+					fBundleDescription.inititialize(fConfigurations[ix]);
 				}
-			);
-			
-					
-		Group c2= createGroup(c, "Main", 2); //$NON-NLS-1$
-			createLabel(c2, Util.getString("page1.mainClass.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-			Composite c7a= createHBox(c2);
-			
-				fMainClass= createText(c7a, MAINCLASS, 1);
-				Button b1= createButton(c7a, SWT.NONE, Util.getString("page1.mainClass.chooseButton.label")); //$NON-NLS-1$
-				b1.addSelectionListener(new SelectionAdapter() {
-					@Override
-					public void widgetSelected(SelectionEvent e) {
-						MessageBox mb= new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
-						mb.setMessage(Util.getString("page1.mainClass.dialog.message")); //$NON-NLS-1$
-						mb.setText(Util.getString("page1.mainClass.dialog.title")); //$NON-NLS-1$
-						mb.open();
-					}
-				});
-				
-				createLabel(c2, Util.getString("page1.arguments.label"), GridData.VERTICAL_ALIGN_BEGINNING); //$NON-NLS-1$
-				fArguments= createText(c2, ARGUMENTS, 2);
-					
-		Group c5= createGroup(c, "Destination", 2); //$NON-NLS-1$	
-			createLabel(c5, Util.getString("page1.appName.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-			fAppName= createText(c5, APPNAME, 1);
-		
-			createLabel(c5, Util.getString("page1.appFolder.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-			Composite c3a= createHBox(c5);
-			
-				fLocation= createCombo(c3a, DESTINATIONDIRECTORY);
-				
-				final Button browse= createButton(c3a, SWT.NONE, Util.getString("page1.appFolder.browseButton.label")); //$NON-NLS-1$
-				browse.addSelectionListener(new SelectionAdapter() {
-					@Override
-					public void widgetSelected(SelectionEvent e) {
-						DirectoryDialog dd= new DirectoryDialog(browse.getShell(), SWT.SAVE);
-						dd.setMessage(Util.getString("page1.appFolder.browseDialog.message")); //$NON-NLS-1$
-						dd.setText(Util.getString("page1.appFolder.browseDialog.title")); //$NON-NLS-1$
-						String name= dd.open();
-						if (name != null) {
-							fLocation.setText(name);
-						}
-					}
-				});
-		
-		Group g6= createGroup(c, "Options", 2); //$NON-NLS-1$
-		
-			createLabel(g6, Util.getString("page1.jvm.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-			
-			Composite c8= createComposite(g6, 4);
-			
-				fJVMVersion= new Combo(c8, SWT.READ_ONLY);
-				for (int i= 0; i < JVMS.length; i++) {
-					fJVMVersion.add(JVMS[i]);
+			}
+		});
+
+		Group c2 = createGroup(c, "Main", 2); //$NON-NLS-1$
+		createLabel(c2, Util.getString("page1.mainClass.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+		Composite c7a = createHBox(c2);
+
+		fMainClass = createText(c7a, MAINCLASS, 1);
+		Button b1 = createButton(c7a, SWT.NONE, Util.getString("page1.mainClass.chooseButton.label")); //$NON-NLS-1$
+		b1.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				MessageBox mb = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
+				mb.setMessage(Util.getString("page1.mainClass.dialog.message")); //$NON-NLS-1$
+				mb.setText(Util.getString("page1.mainClass.dialog.title")); //$NON-NLS-1$
+				mb.open();
+			}
+		});
+
+		createLabel(c2, Util.getString("page1.arguments.label"), GridData.VERTICAL_ALIGN_BEGINNING); //$NON-NLS-1$
+		fArguments = createText(c2, ARGUMENTS, 2);
+
+		Group c5 = createGroup(c, "Destination", 2); //$NON-NLS-1$
+		createLabel(c5, Util.getString("page1.appName.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+		fAppName = createText(c5, APPNAME, 1);
+
+		createLabel(c5, Util.getString("page1.appFolder.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+		Composite c3a = createHBox(c5);
+
+		fLocation = createCombo(c3a, DESTINATIONDIRECTORY);
+
+		final Button browse = createButton(c3a, SWT.NONE, Util.getString("page1.appFolder.browseButton.label")); //$NON-NLS-1$
+		browse.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				DirectoryDialog dd = new DirectoryDialog(browse.getShell(), SWT.SAVE | SWT.SHEET);
+				dd.setMessage(Util.getString("page1.appFolder.browseDialog.message")); //$NON-NLS-1$
+				dd.setText(Util.getString("page1.appFolder.browseDialog.title")); //$NON-NLS-1$
+				String name = dd.open();
+				if (name != null) {
+					fLocation.setText(name);
 				}
-				fJVMVersion.setText(JVMS[4]);
-				hookField(fJVMVersion, JVMVERSION);
-				createLabel(c8, "      ", GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-				createLabel(c8, Util.getString("page1.useSWT.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-				fUseSWT= createButton(c8, SWT.CHECK, null);
-				hookButton(fUseSWT, USES_SWT);
-			
-			createLabel(g6, Util.getString("page1.appIcon.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
-			Composite c7= createComposite(g6, 2);
-				fIconFileName= createText(c7, ICONFILE, 1);
-				final Button b= createButton(c7, SWT.NONE, Util.getString("page1.appIcon.chooseButton.label")); //$NON-NLS-1$
-				b.addSelectionListener(new SelectionAdapter() {
-					@Override
-					public void widgetSelected(SelectionEvent e) {
-						FileDialog fd= new FileDialog(b.getShell(), SWT.OPEN);
-						fd.setText(Util.getString("page1.appIcon.chooseDialog.title")); //$NON-NLS-1$
-						fd.setFilterExtensions(new String[] { "icns" }); //$NON-NLS-1$
-						String name= fd.open();
-						if (name != null) {
-							fIconFileName.setText(name);
-						}
-					}
-				});
-			
+			}
+		});
+
+		Group g6 = createGroup(c, "Options", 2); //$NON-NLS-1$
+
+		createLabel(g6, Util.getString("page1.jvm.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+
+		Composite c8 = createComposite(g6, 4);
+
+		fJVMVersion = new Combo(c8, SWT.READ_ONLY);
+		for (int i = 0; i < JVMS.length; i++) {
+			fJVMVersion.add(JVMS[i]);
+		}
+		fJVMVersion.setText(JVMS[4]);
+		hookField(fJVMVersion, JVMVERSION);
+		createLabel(c8, "      ", GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+		createLabel(c8, Util.getString("page1.useSWT.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+		fUseSWT = createButton(c8, SWT.CHECK, null);
+		hookButton(fUseSWT, USES_SWT);
+
+		createLabel(g6, Util.getString("page1.appIcon.label"), GridData.VERTICAL_ALIGN_CENTER); //$NON-NLS-1$
+		Composite c7 = createComposite(g6, 2);
+		fIconFileName = createText(c7, ICONFILE, 1);
+		final Button b = createButton(c7, SWT.NONE, Util.getString("page1.appIcon.chooseButton.label")); //$NON-NLS-1$
+		b.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				FileDialog fd = new FileDialog(b.getShell(), SWT.OPEN | SWT.SHEET);
+				fd.setText(Util.getString("page1.appIcon.chooseDialog.title")); //$NON-NLS-1$
+				fd.setFilterExtensions(new String[] { "icns" }); //$NON-NLS-1$
+				String name = fd.open();
+				if (name != null) {
+					fIconFileName.setText(name);
+				}
+			}
+		});
+
 	}
-	
+
 	@Override
 	void enterPage() {
 		super.enterPage();
 		initCombo(fLaunchConfigs);
 	}
-	
+
 	@Override
 	public void propertyChange(PropertyChangeEvent event) {
-		if (fAppName != null)
-		 {
+		if (fAppName != null) {
 			fAppName.setText(fBundleDescription.get(APPNAME, "")); //$NON-NLS-1$
 		}
-		if (fMainClass != null)
-		 {
+		if (fMainClass != null) {
 			fMainClass.setText(fBundleDescription.get(MAINCLASS, "")); //$NON-NLS-1$
 		}
-		if (fJVMVersion != null)
-		 {
+		if (fJVMVersion != null) {
 			fJVMVersion.setText(fBundleDescription.get(JVMVERSION, "")); //$NON-NLS-1$
 		}
 		if (fUseSWT != null) {
 			fUseSWT.setSelection(fBundleDescription.get(USES_SWT, false));
 		}
 	}
-	
+
 	@Override
 	public boolean isPageComplete() {
 		return fAppName != null && fAppName.getText().length() > 0 && fLocation.getText().length() > 0;
 	}
 
 	// private stuff
-	
+
 	private void collectLaunchConfigs() {
-		ArrayList<ILaunchConfiguration> configs= new ArrayList<ILaunchConfiguration>();
-		ILaunchManager manager= DebugPlugin.getDefault().getLaunchManager();
-		ILaunchConfigurationType type= manager.getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
+		ArrayList<ILaunchConfiguration> configs = new ArrayList<ILaunchConfiguration>();
+		ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
+		ILaunchConfigurationType type = manager.getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
 		try {
-			ILaunchConfiguration[] configurations= manager.getLaunchConfigurations(type);
-			for (int i= 0; i < configurations.length; i++) {
-				ILaunchConfiguration configuration= configurations[i];
+			ILaunchConfiguration[] configurations = manager.getLaunchConfigurations(type);
+			for (int i = 0; i < configurations.length; i++) {
+				ILaunchConfiguration configuration = configurations[i];
 				if (BundleDescription.verify(configuration)) {
 					configs.add(configuration);
 				}
 			}
-		} catch (CoreException e) {
+		}
+		catch (CoreException e) {
 			//
 		}
-		fConfigurations= configs.toArray(new ILaunchConfiguration[configs.size()]);
+		fConfigurations = configs.toArray(new ILaunchConfiguration[configs.size()]);
 		Arrays.sort(fConfigurations, new Comparator<Object>() {
 			@Override
 			public int compare(Object o1, Object o2) {
-				ILaunchConfiguration lc1= (ILaunchConfiguration) o1;
-				ILaunchConfiguration lc2= (ILaunchConfiguration) o2;
+				ILaunchConfiguration lc1 = (ILaunchConfiguration) o1;
+				ILaunchConfiguration lc2 = (ILaunchConfiguration) o2;
 				return lc1.getName().compareTo(lc2.getName());
 			}
 
@@ -232,23 +224,23 @@
 			}
 		});
 	}
-	
+
 	private void fillCombo(Combo c) {
 		collectLaunchConfigs();
-		for (int i= 0; i < fConfigurations.length; i++) {
-			ILaunchConfiguration configuration= fConfigurations[i];
+		for (int i = 0; i < fConfigurations.length; i++) {
+			ILaunchConfiguration configuration = fConfigurations[i];
 			c.add(configuration.getName());
 		}
 	}
-	
+
 	private void initCombo(Combo c) {
-		IStructuredSelection sel= ((MacBundleWizard)getWizard()).getSelection();
-		Object o= sel.getFirstElement();
+		IStructuredSelection sel = ((MacBundleWizard) getWizard()).getSelection();
+		Object o = sel.getFirstElement();
 		if (o instanceof IJavaElement) {
-			IJavaProject project= ((IJavaElement) o).getJavaProject();
+			IJavaProject project = ((IJavaElement) o).getJavaProject();
 			if (project != null) {
-				for (int i= 0; i < fConfigurations.length; i++) {
-					ILaunchConfiguration configuration= fConfigurations[i];
+				for (int i = 0; i < fConfigurations.length; i++) {
+					ILaunchConfiguration configuration = fConfigurations[i];
 					if (BundleDescription.matches(configuration, project)) {
 						c.setText(configuration.getName());
 						fBundleDescription.inititialize(configuration);
@@ -257,5 +249,5 @@
 				}
 			}
 		}
-	}	
+	}
 }
diff --git a/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage2.java b/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage2.java
index eae7c7f..dd03bf4 100644
--- a/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage2.java
+++ b/org.eclipse.jdt.launching.ui.macosx/src/org/eclipse/jdt/internal/ui/macbundler/BundleWizardPage2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -56,7 +56,7 @@
 			addButton1.addSelectionListener(new SelectionAdapter() {
 				@Override
 				public void widgetSelected(SelectionEvent e) {
-					FileDialog fd= new FileDialog(addButton1.getShell(), SWT.OPEN);
+				FileDialog fd = new FileDialog(addButton1.getShell(), SWT.OPEN | SWT.SHEET);
 					fd.setText(Util.getString("page2.chooseFileDialog.title")); //$NON-NLS-1$
 					String path= fd.open();
 					if (path != null) {
@@ -70,7 +70,7 @@
 			addButton2.addSelectionListener(new SelectionAdapter() {
 				@Override
 				public void widgetSelected(SelectionEvent e) {
-					DirectoryDialog fd= new DirectoryDialog(addButton2.getShell(), SWT.OPEN);
+				DirectoryDialog fd = new DirectoryDialog(addButton2.getShell(), SWT.OPEN | SWT.SHEET);
 					fd.setText(Util.getString("page2.chooseFolder.dialog.title")); //$NON-NLS-1$
 					String path= fd.open();
 					if (path != null) {
diff --git a/org.eclipse.jdt.launching/.settings/.api_filters b/org.eclipse.jdt.launching/.settings/.api_filters
index 0da98d6..e437596 100644
--- a/org.eclipse.jdt.launching/.settings/.api_filters
+++ b/org.eclipse.jdt.launching/.settings/.api_filters
@@ -1,5 +1,13 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.jdt.launching" version="2">
+    <resource path="launching/org/eclipse/jdt/launching/IRuntimeClasspathEntryResolver.java" type="org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver">
+        <filter comment="New method is a default method that delegates to an existing method" id="404000815">
+            <message_arguments>
+                <message_argument value="org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver"/>
+                <message_argument value="resolveRuntimeClasspathEntry(IRuntimeClasspathEntry, IJavaProject, boolean)"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="launching/org/eclipse/jdt/launching/sourcelookup/LocalFileStorage.java" type="org.eclipse.jdt.launching.sourcelookup.LocalFileStorage">
         <filter comment="Known illegal extension" id="571473929">
             <message_arguments>
diff --git a/org.eclipse.jdt.launching/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jdt.launching/.settings/org.eclipse.jdt.core.prefs
index 60292b9..d4306a0 100644
--- a/org.eclipse.jdt.launching/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jdt.launching/.settings/org.eclipse.jdt.core.prefs
@@ -220,10 +220,10 @@
 org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert

 org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert

diff --git a/org.eclipse.jdt.launching/META-INF/MANIFEST.MF b/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
index cd66bdb..3222a4a 100644
--- a/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
@@ -2,15 +2,17 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.launching; singleton:=true
-Bundle-Version: 3.9.52.qualifier
+Bundle-Version: 3.10.0.qualifier
 Bundle-Activator: org.eclipse.jdt.internal.launching.LaunchingPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.jdt.internal.launching;x-friends:="org.eclipse.jdt.debug.ui,org.eclipse.jdt.launching.macosx",
  org.eclipse.jdt.internal.launching.environments;x-internal:=true,
+ org.eclipse.jdt.internal.launching.sourcelookup.advanced;x-internal:=true,
  org.eclipse.jdt.launching,
  org.eclipse.jdt.launching.environments,
  org.eclipse.jdt.launching.sourcelookup,
+ org.eclipse.jdt.launching.sourcelookup.advanced,
  org.eclipse.jdt.launching.sourcelookup.containers
 Require-Bundle: org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
  org.eclipse.jdt.core;bundle-version="[3.8.0,4.0.0)",
@@ -23,3 +25,4 @@
 Bundle-ActivationPolicy: lazy
 Import-Package: com.ibm.icu.text
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: org.eclipse.jdt.launching
diff --git a/org.eclipse.jdt.launching/build.properties b/org.eclipse.jdt.launching/build.properties
index 4d9e533..019787e 100644
--- a/org.eclipse.jdt.launching/build.properties
+++ b/org.eclipse.jdt.launching/build.properties
@@ -14,6 +14,7 @@
                java.policy.applet,\
                .,\
                lib/launchingsupport.jar,\
+               lib/javaagent-shaded.jar,\
                META-INF/,\
                .options
 
@@ -27,4 +28,4 @@
 
 javacWarnings..=-unavoidableGenericProblems
 customBuildCallbacks = customBuildCallbacks.xml
-customBuildCallbacks.failonerror = true
\ No newline at end of file
+customBuildCallbacks.failonerror = true
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultEntryResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultEntryResolver.java
index 90023ff..33f0db2 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultEntryResolver.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultEntryResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -49,11 +49,22 @@
 	 */
 	@Override
 	public IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
+		return resolveRuntimeClasspathEntry(entry, project, false);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver#resolveRuntimeClasspathEntry(org.eclipse.jdt.launching.IRuntimeClasspathEntry,
+	 * org.eclipse.jdt.core.IJavaProject, boolean)
+	 */
+	@Override
+	public IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project, boolean excludeTestCode) throws CoreException {
 		IRuntimeClasspathEntry2 entry2 = (IRuntimeClasspathEntry2)entry;
-		IRuntimeClasspathEntry[] entries = entry2.getRuntimeClasspathEntries(null);
+		IRuntimeClasspathEntry[] entries = entry2.getRuntimeClasspathEntries(excludeTestCode);
 		List<IRuntimeClasspathEntry> resolved = new ArrayList<>();
 		for (int i = 0; i < entries.length; i++) {
-			IRuntimeClasspathEntry[] temp = JavaRuntime.resolveRuntimeClasspathEntry(entries[i], project);
+			IRuntimeClasspathEntry[] temp = JavaRuntime.resolveRuntimeClasspathEntry(entries[i], project, excludeTestCode);
 			for (int j = 0; j < temp.length; j++) {
 				resolved.add(temp[j]);
 			}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
index 569eaa2..8dc2675 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/DefaultProjectClasspathEntry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2017 IBM Corporation and others.
+ *  Copyright (c) 2000, 2018 IBM Corporation and others.
  *  All rights reserved. This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License v1.0
  *  which accompanies this distribution, and is available at
@@ -27,6 +27,7 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
 import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
 import org.eclipse.jdt.launching.IRuntimeContainerComparator;
 import org.eclipse.jdt.launching.JavaRuntime;
@@ -136,10 +137,22 @@
 	 */
 	@Override
 	public IRuntimeClasspathEntry[] getRuntimeClasspathEntries(ILaunchConfiguration configuration) throws CoreException {
+		boolean excludeTestCode = configuration != null
+				&& configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false);
+		return getRuntimeClasspathEntries(excludeTestCode);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.eclipse.jdt.launching.IRuntimeClasspathEntry2#getRuntimeClasspathEntries(boolean)
+	 */
+	@Override
+	public IRuntimeClasspathEntry[] getRuntimeClasspathEntries(boolean excludeTestCode) throws CoreException {
 		IClasspathEntry entry = JavaCore.newProjectEntry(getJavaProject().getProject().getFullPath());
 		List<Object> classpathEntries = new ArrayList<>(5);
 		List<IClasspathEntry> expanding = new ArrayList<>(5);
-		expandProject(entry, classpathEntries, expanding);
+		expandProject(entry, classpathEntries, expanding, excludeTestCode);
 		IRuntimeClasspathEntry[] runtimeEntries = new IRuntimeClasspathEntry[classpathEntries.size()];
 		for (int i = 0; i < runtimeEntries.length; i++) {
 			Object e = classpathEntries.get(i);
@@ -161,17 +174,20 @@
 	}
 
 	/**
-	 * Returns the transitive closure of classpath entries for the
-	 * given project entry.
+	 * Returns the transitive closure of classpath entries for the given project entry.
 	 *
-	 * @param projectEntry project classpath entry
-	 * @param expandedPath a list of entries already expanded, should be empty
-	 * to begin, and contains the result
-	 * @param expanding a list of projects that have been or are currently being
-	 * expanded (to detect cycles)
-	 * @exception CoreException if unable to expand the classpath
+	 * @param projectEntry
+	 *            project classpath entry
+	 * @param expandedPath
+	 *            a list of entries already expanded, should be empty to begin, and contains the result
+	 * @param expanding
+	 *            a list of projects that have been or are currently being expanded (to detect cycles)
+	 * @param excludeTestCode
+	 *            if true, test dependencies will be excluded
+	 * @exception CoreException
+	 *                if unable to expand the classpath
 	 */
-	private void expandProject(IClasspathEntry projectEntry, List<Object> expandedPath, List<IClasspathEntry> expanding) throws CoreException {
+	private void expandProject(IClasspathEntry projectEntry, List<Object> expandedPath, List<IClasspathEntry> expanding, boolean excludeTestCode) throws CoreException {
 		expanding.add(projectEntry);
 		// 1. Get the raw classpath
 		// 2. Replace source folder entries with a project entry
@@ -194,6 +210,9 @@
 		boolean projectAdded = false;
 		for (int i = 0; i < buildPath.length; i++) {
 			IClasspathEntry classpathEntry = buildPath[i];
+			if (excludeTestCode && classpathEntry.isTest()) {
+				continue;
+			}
 			if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
 				if (!projectAdded) {
 					projectAdded = true;
@@ -220,7 +239,7 @@
 				switch (entry.getEntryKind()) {
 					case IClasspathEntry.CPE_PROJECT:
 						if (!expanding.contains(entry)) {
-							expandProject(entry, expandedPath, expanding);
+							expandProject(entry, expandedPath, expanding, excludeTestCode);
 						}
 						break;
 					case IClasspathEntry.CPE_CONTAINER:
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JRERuntimeClasspathEntryResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JRERuntimeClasspathEntryResolver.java
index 381c0c9..e9a90de 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JRERuntimeClasspathEntryResolver.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JRERuntimeClasspathEntryResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java
index 06f626e..8da9633 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -151,6 +151,7 @@
 
 	public static String vmInstall_assert_idNotNull;
 	public static String vmInstall_assert_typeNotNull;
+	public static String vmInstall_could_not_determine_java_Version;
 
 	public static String vmInstallType_duplicateVM;
 
@@ -214,6 +215,10 @@
 	public static String ProjectClasspathVariableResolver_2;
 	public static String ProjectClasspathVariableResolver_3;
 
+	public static String VMLogging_1;
+	public static String VMLogging_2;
+	public static String VMLogging_3;
+
 	static {
 		// load message values from bundle file
 		NLS.initializeMessages(BUNDLE_NAME, LaunchingMessages.class);
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties
index 5a28638..6d7b9c3 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2017 IBM Corporation and others.
+# Copyright (c) 2000, 2018 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -111,6 +111,7 @@
 
 vmInstall_assert_idNotNull=id cannot be null
 vmInstall_assert_typeNotNull=VM type cannot be null
+vmInstall_could_not_determine_java_Version=Could not determine Java version for location {0}.
 
 vmInstallType_duplicateVM=Duplicate VM: {0}
 
@@ -196,4 +197,7 @@
 VMDefinitionsContainer_9=Installed JRE of type ''{0}'' removed due to missing install path, name, and id.
 VMDefinitionsContainer_10=Installed JREs
 RunnerBootpathError=Xbootclasspath option have been removed as not supported beyond Java 8.
-RunnerBootpathPError=Xbootclasspath/p option have been removed as not supported beyond Java 8.
\ No newline at end of file
+RunnerBootpathPError=Xbootclasspath/p option have been removed as not supported beyond Java 8.
+VMLogging_1=Restoring vm library location:
+VMLogging_2=Creating Library with Java Install path:
+VMLogging_3=Default Install retrieved:
\ No newline at end of file
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java
index 6711557..bdc2ee4 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/LaunchingPlugin.java
@@ -69,6 +69,7 @@
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport;
 import org.eclipse.jdt.launching.IRuntimeClasspathEntry2;
 import org.eclipse.jdt.launching.IVMConnector;
 import org.eclipse.jdt.launching.IVMInstall;
@@ -423,6 +424,9 @@
 	 * @param info the library information, or <code>null</code> to remove
 	 */
 	public static void setLibraryInfo(String javaInstallPath, LibraryInfo info) {
+		if (isVMLogging()) {
+			LaunchingPlugin.log(LaunchingMessages.VMLogging_2 + javaInstallPath);
+		}
 		if (fgLibraryInfoMap == null) {
 			restoreLibraryInfo();
 		}
@@ -441,6 +445,11 @@
 		saveLibraryInfo();
 	}
 
+	public static boolean isVMLogging() {
+		String vmLogging = System.getProperty("jdt.debug.launching.vmLogging"); //$NON-NLS-1$
+		return "true".equalsIgnoreCase(vmLogging); //$NON-NLS-1$
+	}
+
 	/**
 	 * Return a <code>java.io.File</code> object that corresponds to the specified
 	 * <code>IPath</code> in the plug-in directory.
@@ -509,6 +518,8 @@
 	@Override
 	public void stop(BundleContext context) throws Exception {
 		try {
+			AdvancedSourceLookupSupport.stop();
+
 			DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
 			DebugPlugin.getDefault().removeDebugEventListener(this);
 			ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
@@ -556,6 +567,8 @@
 		ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_CLOSE);
 		DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
 		DebugPlugin.getDefault().addDebugEventListener(this);
+
+		AdvancedSourceLookupSupport.start();
 	}
 
 	/**
@@ -942,6 +955,9 @@
 							String[] extDirs = getPathsFromXML(element, "extensionDirs"); //$NON-NLS-1$
 							String[] endDirs = getPathsFromXML(element, "endorsedDirs"); //$NON-NLS-1$
 							if (location != null) {
+								if (isVMLogging()) {
+									LaunchingPlugin.log(LaunchingMessages.VMLogging_1 + location);
+								}
 								LibraryInfo info = new LibraryInfo(version, bootpath, extDirs, endDirs);
 								fgLibraryInfoMap.put(location, info);
 							}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/ProjectClasspathVariableResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/ProjectClasspathVariableResolver.java
index 9980ff9..5083692 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/ProjectClasspathVariableResolver.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/ProjectClasspathVariableResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2015 IBM Corporation and others.
+ * Copyright (c) 2010, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -55,10 +55,10 @@
 		IJavaProject javaProject = JavaCore.create(proj);
 		if (javaProject.exists()) {
 			IRuntimeClasspathEntry2 defClassPath = (IRuntimeClasspathEntry2) JavaRuntime.newDefaultProjectClasspathEntry(javaProject);
-			IRuntimeClasspathEntry[] entries = defClassPath.getRuntimeClasspathEntries(null);
+			IRuntimeClasspathEntry[] entries = defClassPath.getRuntimeClasspathEntries(false);
 			List<IRuntimeClasspathEntry> collect = new ArrayList<>();
 			for (int i = 0; i < entries.length; i++) {
-				IRuntimeClasspathEntry[] children = JavaRuntime.resolveRuntimeClasspathEntry(entries[i], javaProject);
+				IRuntimeClasspathEntry[] children = JavaRuntime.resolveRuntimeClasspathEntry(entries[i], javaProject, false);
 				for (int j = 0; j < children.length; j++) {
 					collect.add(children[j]);
 				}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntryResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntryResolver.java
index 6906f1b..81cf38a 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntryResolver.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/RuntimeClasspathEntryResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -99,6 +99,14 @@
 		return getResolver().resolveRuntimeClasspathEntry(entry, project);
 	}
 
+	/**
+	 * @see IRuntimeClasspathEntryResolver#resolveRuntimeClasspathEntry(IRuntimeClasspathEntry, IJavaProject, excludeTestCode)
+	 */
+	@Override
+	public IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project, boolean excludeTestCode) throws CoreException {
+		return getResolver().resolveRuntimeClasspathEntry(entry, project, excludeTestCode);
+	}
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.jdt.launching.IRuntimeClasspathEntryResolver2#isVMInstallReference(org.eclipse.jdt.core.IClasspathEntry)
 	 */
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVM.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVM.java
index 4d29c40..35312a3 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVM.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVM.java
@@ -17,6 +17,7 @@
 import org.eclipse.jdt.launching.AbstractVMInstall;
 import org.eclipse.jdt.launching.IVMInstallType;
 import org.eclipse.jdt.launching.IVMRunner;
+import org.eclipse.osgi.util.NLS;
 
 public class StandardVM extends AbstractVMInstall {
 
@@ -68,6 +69,7 @@
                     return version.toString();
                 }
             }
+            LaunchingPlugin.log(NLS.bind(LaunchingMessages.vmInstall_could_not_determine_java_Version, installLocation.getAbsolutePath()));
         }
         return null;
     }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java
index 84a0f16..99b1e5e 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMDebugger.java
@@ -224,6 +224,15 @@
 			arguments.add(convertClassPath(cp));
 		}
 
+		String dependencies = config.getOverrideDependencies();
+		if (dependencies != null && dependencies.length() > 0) {
+			String[] parseArguments = DebugPlugin.parseArguments(dependencies);
+			for (String string : parseArguments) {
+				arguments.add(string);
+			}
+
+		}
+
 		if (isModular(config, fVMInstance)) {
 			arguments.add("-m"); //$NON-NLS-1$
 			arguments.add(config.getModuleDescription() + "/" + config.getClassToLaunch()); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java
index 1e9648b..af3dd37 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMRunner.java
@@ -379,8 +379,7 @@
 			arguments.add("-p"); //$NON-NLS-1$
 			arguments.add(convertClassPath(mp));
 		}
-
-		String[] cp= config.getClassPath();
+		String[] cp = config.getClassPath();
 		int cpidx = -1;
 		if (cp.length > 0) {
 			cpidx = arguments.size();
@@ -388,6 +387,15 @@
 			arguments.add(convertClassPath(cp));
 		}
 
+		String dependencies = config.getOverrideDependencies();
+		if (dependencies != null && dependencies.length() > 0) {
+			String[] parseArguments = DebugPlugin.parseArguments(dependencies);
+			for (String string : parseArguments) {
+				arguments.add(string);
+			}
+
+		}
+
 		if (isModular(config, fVMInstance)) {
 			arguments.add("-m"); //$NON-NLS-1$
 			arguments.add(config.getModuleDescription() + "/" + config.getClassToLaunch()); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
index 4a5357b..a3b7eef 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/StandardVMType.java
@@ -74,6 +74,7 @@
 	private static final String BAR = "|"; //$NON-NLS-1$
 	private static final String RELEASE_FILE = "release"; //$NON-NLS-1$
 	private static final String JAVA_VERSION = "JAVA_VERSION"; //$NON-NLS-1$
+	private static final String JRT_FS_JAR = "jrt-fs.jar"; //$NON-NLS-1$
 
 	public static final String ID_STANDARD_VM_TYPE = "org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType"; //$NON-NLS-1$
 
@@ -441,22 +442,22 @@
 				// Code referencing org.eclipse.jdt.internal.compiler.util.JimageUtil.JRT_FS_JAR looks for this file.
 				IPath sourceRootPath = Path.EMPTY;
 				// src zip moved to lib folder from JDK 9 EA Build 151
-				IPath path = new Path(installLocation.getAbsolutePath()).append("lib").append("src.zip"); //$NON-NLS-1$ //$NON-NLS-2$
+				IPath path = new Path(installLocation.getAbsolutePath()).append(LIB).append(SRC_ZIP);
 				File lib = path.toFile();
 				if (lib.exists() && lib.isFile()) {
 					sourceRootPath = getDefaultSystemLibrarySource(lib); // To attach source if available
 				} else {
-					path = new Path(installLocation.getAbsolutePath()).append("src.zip"); //$NON-NLS-1$
+					path = new Path(installLocation.getAbsolutePath()).append(SRC_ZIP);
 					lib = path.toFile();
 					if (lib.exists() && lib.isFile()) {
 						sourceRootPath = getDefaultSystemLibrarySource(lib); // To attach source if available
 					}
 				}
-				IPath pathName = new Path(installLocation.getAbsolutePath()).append("lib").append("jrt-fs.jar"); //$NON-NLS-1$ //$NON-NLS-2$
+				IPath pathName = new Path(installLocation.getAbsolutePath()).append(LIB).append(JRT_FS_JAR);
 				// From Java 9 149 version, we see that jrt-fs.jar is moved to lib directory so we need to look at both places
 				File jrtfsJar = pathName.toFile();
 				if (!jrtfsJar.exists()) {
-					pathName = new Path(installLocation.getAbsolutePath()).append("jrt-fs.jar"); //$NON-NLS-1$
+					pathName = new Path(installLocation.getAbsolutePath()).append(JRT_FS_JAR);
 				}
 
 				LibraryLocation libraryLocation = new LibraryLocation(pathName,
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/VariableClasspathResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/VariableClasspathResolver.java
index 53350df..580f1b3 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/VariableClasspathResolver.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/VariableClasspathResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/ExecutionEnvironment.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/ExecutionEnvironment.java
index ba2dd6f..d127927 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/ExecutionEnvironment.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/environments/ExecutionEnvironment.java
@@ -480,6 +480,7 @@
 			profile.setProperty(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_9);
 			profile.setProperty(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_9);
 			profile.setProperty(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_9);
+			profile.setProperty(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
 		}
 	}
 
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedRemoteJavaLaunchDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedRemoteJavaLaunchDelegate.java
new file mode 100644
index 0000000..664b8b0
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedRemoteJavaLaunchDelegate.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import org.eclipse.jdt.internal.launching.JavaRemoteApplicationLaunchConfigurationDelegate;
+
+public class AdvancedRemoteJavaLaunchDelegate extends JavaRemoteApplicationLaunchConfigurationDelegate {
+
+	public AdvancedRemoteJavaLaunchDelegate() {
+		allowAdvancedSourcelookup();
+	}
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedSourceLookupDirector.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedSourceLookupDirector.java
new file mode 100644
index 0000000..49cf93b
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedSourceLookupDirector.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
+import org.eclipse.jdt.internal.launching.JavaSourceLookupDirector;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookupParticipant;
+import org.eclipse.jdt.launching.sourcelookup.containers.JavaSourceLookupParticipant;
+
+public class AdvancedSourceLookupDirector extends JavaSourceLookupDirector {
+	// Note to self: JavaSourceLookupDirector parent class is useful because it allows custom source lookup path in the launch configuration.
+
+	public static final String ID = "org.eclipse.jdt.launching.sourceLocator.JavaAdvancedSourceLookupDirector"; //$NON-NLS-1$
+
+	private final String mode;
+
+	public AdvancedSourceLookupDirector() {
+		this(null);
+	}
+
+	public AdvancedSourceLookupDirector(String mode) {
+		this.mode = mode;
+	}
+
+	@Override
+	public void initializeParticipants() {
+		final List<ISourceLookupParticipant> participants = new ArrayList<>();
+		if (mode == null || ILaunchManager.DEBUG_MODE.equals(mode)) {
+			participants.addAll(getSourceLookupParticipants());
+		}
+
+		// fall-back to default JDT behaviour if we can't find matching sources
+		// in most cases this means scanning workspace for any source or binary with matching name
+		participants.add(new JavaSourceLookupParticipant());
+
+		addParticipants(participants.toArray(new ISourceLookupParticipant[participants.size()]));
+	}
+
+	protected Collection<ISourceLookupParticipant> getSourceLookupParticipants() {
+		return Collections.singleton(new AdvancedSourceLookupParticipant());
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedSourceLookupSupport.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedSourceLookupSupport.java
new file mode 100644
index 0000000..f09fcdb
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/AdvancedSourceLookupSupport.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2015-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.Launch;
+import org.eclipse.debug.core.model.IPersistableSourceLocator;
+import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
+import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
+import org.eclipse.jdt.internal.launching.LaunchingPlugin;
+
+public class AdvancedSourceLookupSupport {
+
+	// TODO consider moving to LaunchingPlugin
+	public static final String ID_sourceContainerResolvers = LaunchingPlugin.ID_PLUGIN + ".sourceContainerResolvers"; //$NON-NLS-1$
+
+	// TODO consider moving to LaunchingPlugin
+	public static final String ID_workspaceProjectDescribers = LaunchingPlugin.ID_PLUGIN + ".workspaceProjectDescribers"; //$NON-NLS-1$
+
+	private static BackgroundProcessingJob backgroundJob;
+
+	private static volatile WorkspaceProjectSourceContainers workspaceProjects;
+	private static final Lock workspaceProjectsLock = new ReentrantLock();
+
+	private AdvancedSourceLookupSupport() {
+	}
+
+	public static void start() {
+		backgroundJob = new BackgroundProcessingJob();
+	}
+
+	public static void stop() {
+		backgroundJob.cancel();
+		backgroundJob = null;
+
+		workspaceProjectsLock.lock();
+		try {
+			if (workspaceProjects != null) {
+				workspaceProjects.close();
+				workspaceProjects = null;
+			}
+		}
+		finally {
+			workspaceProjectsLock.unlock();
+		}
+	}
+
+	public static void schedule(IRunnableWithProgress task) {
+		backgroundJob.schedule(task);
+	}
+
+	public static WorkspaceProjectSourceContainers getWorkspaceJavaProjects(IProgressMonitor monitor) throws CoreException {
+		return getWorkspaceJavaProjects0(monitor);
+	}
+
+	private static WorkspaceProjectSourceContainers getWorkspaceJavaProjects0(IProgressMonitor monitor) throws CoreException {
+		// this is convoluted, but I could not think of a simpler implementation
+
+		// when monitor==null, we are most likely on UI thread and must not block, hence immediate return
+		if (monitor == null || workspaceProjects != null) {
+			return workspaceProjects;
+		}
+
+		// when monitor!=null, try to get the lock but check for cancellation periodically
+		try {
+			while (!workspaceProjectsLock.tryLock(500, TimeUnit.MILLISECONDS)) {
+				if (monitor.isCanceled()) {
+					return workspaceProjects;
+				}
+			}
+		}
+		catch (InterruptedException e) {
+			Thread.currentThread().interrupt(); // restore interrupted status
+			return workspaceProjects;
+		}
+
+		// got the lock, do the initialization if another thread didn't do it already
+		// note that double-check locking is okay on java 5+ with volatile fields
+		try {
+			if (workspaceProjects == null) {
+				WorkspaceProjectSourceContainers _workspaceProjects = new WorkspaceProjectSourceContainers();
+				_workspaceProjects.initialize(monitor);
+
+				// assign only fully initialized instance, otherwise monitor==null branch above may misbehave
+				workspaceProjects = _workspaceProjects;
+			}
+		}
+		finally {
+			// release the lock in finally{} block
+			workspaceProjectsLock.unlock();
+		}
+
+		return workspaceProjects;
+	}
+
+	public static String getJavaagentString() {
+		return "-javaagent:\"" + getJavaagentLocation() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	public static String getJavaagentLocation() {
+		return LaunchingPlugin.getFileInPlugin(new Path("lib/javaagent-shaded.jar")).getAbsolutePath(); //$NON-NLS-1$
+	}
+
+	/**
+	 * Workaround a deficiency of ISourceLookupParticipant API, which does not provide access to a progress monitor.
+	 *
+	 * <p>
+	 * This method can be called in three different cases:
+	 * <ol>
+	 * <li>from UI thread, in which case {@code null} is return. this tells the caller to only perform fast operations (i.e. cache lookups) on this
+	 * thread and submit any long-running operations as background jobs
+	 * <li>from background job with existing IProgressMonitor, in which case the monitor is returned
+	 * <li>from background job without IProgressMonitor, in which case {@link NullProgressMonitor} is returned.
+	 * </ol>
+	 */
+	public static IProgressMonitor getContextMonitor(IProgressMonitor monitor) {
+		if (monitor == null) {
+			Job job = Job.getJobManager().currentJob();
+			if (job != null) {
+				// current implementation can perform workspace project cache initialization on system job without any user feedback
+				// although eclipse ui remains responsive, source lookup will appear to do nothing until initialization is complete
+				// a fix requires changes to ISourceLookupParticipant#findSourceElements API to accept user-visible progress monitor
+				monitor = new NullProgressMonitor();
+			}
+		}
+		return monitor;
+	}
+
+	/**
+	 * Returns a launch object to use when launching the given launch configuration in the given mode. The returned launch object is preconfigured to
+	 * use {@link AdvancedSourceLookupDirector} as the source locator.
+	 */
+	public static ILaunch createAdvancedLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
+		return new Launch(configuration, mode, createSourceLocator(AdvancedSourceLookupDirector.ID, configuration));
+	}
+
+	/**
+	 * Creates and returns new {@link IPersistableSourceLocator} of the specified type and with the provided configuration.
+	 */
+	public static IPersistableSourceLocator createSourceLocator(String type, ILaunchConfiguration configuration) throws CoreException {
+		ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+
+		IPersistableSourceLocator locator = launchManager.newSourceLocator(type);
+		String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null);
+		if (memento == null) {
+			locator.initializeDefaults(configuration);
+		} else {
+			if (locator instanceof IPersistableSourceLocator2) {
+				((IPersistableSourceLocator2) locator).initializeFromMemento(memento, configuration);
+			} else {
+				locator.initializeFromMemento(memento);
+			}
+		}
+
+		return locator;
+	}
+
+	public static boolean isAdvancedSourcelookupEnabled() {
+		return Platform.getPreferencesService().getBoolean(JDIDebugPlugin.getUniqueIdentifier(), JDIDebugPlugin.PREF_ENABLE_ADVANCED_SOURCELOOKUP, true, null);
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/BackgroundProcessingJob.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/BackgroundProcessingJob.java
new file mode 100644
index 0000000..723ed2e
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/BackgroundProcessingJob.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.internal.launching.LaunchingPlugin;
+
+/**
+ * Simple background request processing queue implemented using {@link Job} API. Requests are executed in the order they arrive. Request execution
+ * delayed by {@value #EXECUTION_DELAY} milliseconds and all requests submitted during this period will be processed together.
+ */
+public class BackgroundProcessingJob extends Job {
+	private static final long EXECUTION_DELAY = 1000L;
+
+	private final ArrayList<IRunnableWithProgress> queue = new ArrayList<>();
+
+	public BackgroundProcessingJob() {
+		super(Messages.BackgroundProcessingJob_name);
+	}
+
+	@Override
+	protected IStatus run(IProgressMonitor monitor) {
+		ArrayList<IRunnableWithProgress> tasks;
+		synchronized (this.queue) {
+			tasks = new ArrayList<>(this.queue);
+			this.queue.clear();
+		}
+
+		SubMonitor progress = SubMonitor.convert(monitor, tasks.size());
+
+		List<IStatus> errors = new ArrayList<>();
+
+		for (IRunnableWithProgress task : tasks) {
+			try {
+				task.run(progress.split(1));
+			}
+			catch (CoreException e) {
+				errors.add(e.getStatus());
+			}
+		}
+
+		if (errors.isEmpty()) {
+			return Status.OK_STATUS;
+		}
+
+		if (errors.size() == 1) {
+			return errors.get(0);
+		}
+
+		return new MultiStatus(LaunchingPlugin.ID_PLUGIN, IStatus.ERROR, errors.toArray(new IStatus[errors.size()]), Messages.BackgroundProcessingJob_failed, null);
+	}
+
+	public void schedule(IRunnableWithProgress task) {
+		synchronized (queue) {
+			queue.add(task);
+			schedule(EXECUTION_DELAY);
+		}
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/CompositeSourceContainer.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/CompositeSourceContainer.java
new file mode 100644
index 0000000..8f7c030
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/CompositeSourceContainer.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
+
+public class CompositeSourceContainer extends org.eclipse.debug.core.sourcelookup.containers.CompositeSourceContainer {
+
+	private final ISourceContainer[] members;
+
+	private CompositeSourceContainer(Collection<ISourceContainer> members) {
+		this.members = members.toArray(new ISourceContainer[members.size()]);
+	}
+
+	@Override
+	public ISourceContainer[] getSourceContainers() throws CoreException {
+		return members;
+	}
+
+	@Override
+	public String getName() {
+		return null;
+	}
+
+	@Override
+	public ISourceContainerType getType() {
+		return null;
+	}
+
+	@Override
+	protected ISourceContainer[] createSourceContainers() throws CoreException {
+		return null;
+	}
+
+	@Override
+	public void dispose() {
+		super.dispose();
+		for (ISourceContainer member : members) {
+			member.dispose();
+		}
+		Arrays.fill(members, null);
+	}
+
+	public static ISourceContainer compose(Collection<ISourceContainer> containers) {
+		if (containers.isEmpty()) {
+			throw new IllegalArgumentException();
+		}
+		if (containers.size() == 1) {
+			return containers.iterator().next();
+		}
+		return new CompositeSourceContainer(containers);
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/DefaultProjectDescriber.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/DefaultProjectDescriber.java
new file mode 100644
index 0000000..6f1c83e
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/DefaultProjectDescriber.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import static org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup.getClasspath;
+import static org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup.getOutputDirectories;
+import static org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup.isSourceProject;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.sourcelookup.advanced.IWorkspaceProjectDescriber;
+import org.eclipse.jdt.launching.sourcelookup.containers.JavaProjectSourceContainer;
+
+public class DefaultProjectDescriber implements IWorkspaceProjectDescriber {
+
+	@Override
+	public void describeProject(IJavaProject project, IJavaProjectSourceDescription description) throws CoreException {
+		if (isSourceProject(project)) {
+			description.addDependencies(getClasspath(project));
+			getOutputDirectories(project).forEach(f -> description.addLocation(f));
+			description.addSourceContainerFactory(() -> new JavaProjectSourceContainer(project));
+		}
+	}
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/FileHashing.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/FileHashing.java
new file mode 100644
index 0000000..09ce870
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/FileHashing.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Helpers to compute file content digests. Provides long-lived hasher instance with bounded cache of most recently requested files, which is useful
+ * to handle source lookup requests. Also provides factory of hasher instances with unbounded caches, which is useful to perform bulk workspace
+ * indexing.
+ */
+public class FileHashing {
+
+	public static interface Hasher {
+		Object hash(File file);
+	}
+
+	// default hasher with bounded cache.
+	// this is used when performing source lookup and number of unique files requested during the same debugging session is likely to be small.
+	private static final HasherImpl HASHER = new HasherImpl(5000);
+
+	/**
+	 * Returns default long-lived Hasher instance with bounded hash cache.
+	 */
+	public static Hasher hasher() {
+		return HASHER;
+	}
+
+	/**
+	 * Returns new Hasher instance with unbounded hash cache, useful for bulk hashing of projects and their dependencies.
+	 */
+	public static Hasher newHasher() {
+		return new HasherImpl(HASHER);
+	}
+
+	private static class CacheKey {
+		public final File file;
+
+		private final long length;
+
+		private final long lastModified;
+
+		public CacheKey(File file) throws IOException {
+			this.file = file.getCanonicalFile();
+			this.length = file.length();
+			this.lastModified = file.lastModified();
+		}
+
+		@Override
+		public int hashCode() {
+			int hash = 17;
+			hash = hash * 31 + file.hashCode();
+			hash = hash * 31 + (int) length;
+			hash = hash * 31 + (int) lastModified;
+			return hash;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (obj == this) {
+				return true;
+			}
+			if (!(obj instanceof CacheKey)) {
+				return false;
+			}
+			CacheKey other = (CacheKey) obj;
+			return file.equals(other.file) && length == other.length && lastModified == other.lastModified;
+		}
+	}
+
+	private static class HashCode {
+		private final byte[] bytes;
+
+		public HashCode(byte[] bytes) {
+			this.bytes = bytes; // assumes this class "owns" the array from now on
+		}
+
+		@Override
+		public int hashCode() {
+			return Arrays.hashCode(bytes);
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (obj == this) {
+				return true;
+			}
+			if (!(obj instanceof HashCode)) {
+				return false;
+			}
+			return Arrays.equals(bytes, ((HashCode) obj).bytes);
+		}
+
+		@Override
+		public final String toString() {
+			StringBuilder sb = new StringBuilder(2 * bytes.length);
+			for (byte b : bytes) {
+				sb.append(hexDigits[(b >> 4) & 0xf]).append(hexDigits[b & 0xf]);
+			}
+			return sb.toString();
+		}
+
+		private static final char[] hexDigits = "0123456789abcdef".toCharArray(); //$NON-NLS-1$
+	}
+
+	private static class HasherImpl implements Hasher {
+
+		private final Map<CacheKey, HashCode> cache;
+
+		@SuppressWarnings("serial")
+		public HasherImpl(int cacheSize) {
+			this.cache = new LinkedHashMap<CacheKey, HashCode>() {
+				@Override
+				protected boolean removeEldestEntry(Map.Entry<CacheKey, HashCode> eldest) {
+					return size() > cacheSize;
+				}
+			};
+		}
+
+		public HasherImpl(HasherImpl initial) {
+			this.cache = new LinkedHashMap<>(initial.cache);
+		}
+
+		@Override
+		public Object hash(File file) {
+			if (file == null || !file.isFile()) {
+				return null;
+			}
+			try {
+				CacheKey cacheKey = new CacheKey(file);
+				synchronized (cache) {
+					HashCode hashCode = cache.get(cacheKey);
+					if (hashCode != null) {
+						return hashCode;
+					}
+				}
+				// don't hold cache lock while hashing file
+				HashCode hashCode = sha1(file);
+				synchronized (cache) {
+					cache.put(cacheKey, hashCode);
+				}
+				return hashCode;
+			}
+			catch (IOException e) {
+				return null; // file does not exist or can't be read
+			}
+		}
+
+	}
+
+	private static HashCode sha1(File file) throws IOException {
+		MessageDigest digest;
+		try {
+			digest = MessageDigest.getInstance("SHA1"); //$NON-NLS-1$
+		}
+		catch (NoSuchAlgorithmException e) {
+			throw new IllegalStateException("Unsupported JVM", e); //$NON-NLS-1$
+		}
+		byte[] buf = new byte[4096];
+		try (InputStream is = new FileInputStream(file)) {
+			int len;
+			while ((len = is.read(buf)) > 0) {
+				digest.update(buf, 0, len);
+			}
+		}
+		return new HashCode(digest.digest());
+	}
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/IJDIHelpers.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/IJDIHelpers.java
new file mode 100644
index 0000000..32a917a
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/IJDIHelpers.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import java.io.File;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IStackFrame;
+
+/**
+ * Helpers to extract source lookup location information from advanced source lookup JSR-45 strata.
+ */
+public interface IJDIHelpers {
+
+	public static final IJDIHelpers INSTANCE = new JDIHelpers();
+
+	/**
+	 * Return classes location the given element was loaded from or {@code null} if the location cannot be determined.
+	 */
+	public File getClassesLocation(Object element) throws DebugException;
+
+	/**
+	 * Returns source path of the given element or {@code null} if the source path cannot be determined. The returned path is relative to a sources
+	 * container.
+	 */
+	public String getSourcePath(Object element) throws DebugException;
+
+	/**
+	 * If the given element is a {@link IStackFrame}, returns classes locations of the stack frames "beneath" the given element. The returned iterable
+	 * does not include {@code null} elements.
+	 * 
+	 * Returns empty iterable if the given element is not a {@link IStackFrame}.
+	 */
+	public Iterable<File> getStackFramesClassesLocations(Object element) throws DebugException;
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/IRunnableWithProgress.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/IRunnableWithProgress.java
new file mode 100644
index 0000000..5e992a3
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/IRunnableWithProgress.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Runnable with progress interface. Almost exact copy of similar interfaces defined in jface and p2.
+ */
+@FunctionalInterface
+public interface IRunnableWithProgress {
+	public void run(IProgressMonitor monitor) throws CoreException;
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JDIHelpers.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JDIHelpers.java
new file mode 100644
index 0000000..057eff9
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JDIHelpers.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaReferenceType;
+import org.eclipse.jdt.debug.core.IJavaStackFrame;
+import org.eclipse.jdt.debug.core.IJavaType;
+import org.eclipse.jdt.debug.core.IJavaValue;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+
+public final class JDIHelpers implements IJDIHelpers {
+
+	// must match ClassfileTransformer.STRATA_ID
+	public static final String STRATA_ID = "jdt"; //$NON-NLS-1$
+
+	JDIHelpers() {
+	}
+
+	// jdt debug boilerplate and other ideas were originally "borrowed" from
+	// org.eclipse.pde.internal.launching.sourcelookup.PDESourceLookupQuery.run()
+
+	@Override
+	public File getClassesLocation(Object element) throws DebugException {
+		IJavaReferenceType declaringType = null;
+		if (element instanceof IJavaStackFrame) {
+			IJavaStackFrame stackFrame = (IJavaStackFrame) element;
+			declaringType = stackFrame.getReferenceType();
+		} else if (element instanceof IJavaObject) {
+			IJavaType javaType = ((IJavaObject) element).getJavaType();
+			if (javaType instanceof IJavaReferenceType) {
+				declaringType = (IJavaReferenceType) javaType;
+			}
+		} else if (element instanceof IJavaReferenceType) {
+			declaringType = (IJavaReferenceType) element;
+		} else if (element instanceof IJavaVariable) {
+			IJavaVariable javaVariable = (IJavaVariable) element;
+			IJavaType javaType = ((IJavaValue) javaVariable.getValue()).getJavaType();
+			if (javaType instanceof IJavaReferenceType) {
+				declaringType = (IJavaReferenceType) javaType;
+			}
+		}
+
+		if (declaringType != null) {
+			String[] locations = declaringType.getSourceNames(STRATA_ID);
+
+			if (locations == null || locations.length < 2) {
+				return null;
+			}
+
+			try {
+				URL url = new URL(locations[1]);
+				if ("file".equals(url.getProtocol())) { //$NON-NLS-1$
+					return new File(url.getPath()).toPath().normalize().toFile();
+				}
+			}
+			catch (MalformedURLException e) {
+				// fall through
+			}
+		}
+
+		return null;
+	}
+
+	@Override
+	public String getSourcePath(Object element) throws DebugException {
+		IJavaReferenceType declaringType = null;
+		if (element instanceof IJavaStackFrame) {
+			IJavaStackFrame stackFrame = (IJavaStackFrame) element;
+			// under JSR 45 source path from the stack frame is more precise than anything derived from the type
+			String sourcePath = stackFrame.getSourcePath(STRATA_ID);
+			if (sourcePath != null) {
+				return sourcePath;
+			}
+
+			declaringType = stackFrame.getReferenceType();
+		} else if (element instanceof IJavaObject) {
+			IJavaType javaType = ((IJavaObject) element).getJavaType();
+			if (javaType instanceof IJavaReferenceType) {
+				declaringType = (IJavaReferenceType) javaType;
+			}
+		} else if (element instanceof IJavaReferenceType) {
+			declaringType = (IJavaReferenceType) element;
+		} else if (element instanceof IJavaVariable) {
+			IJavaType javaType = ((IJavaVariable) element).getJavaType();
+			if (javaType instanceof IJavaReferenceType) {
+				declaringType = (IJavaReferenceType) javaType;
+			}
+		}
+
+		if (declaringType != null) {
+			String[] sourcePaths = declaringType.getSourcePaths(STRATA_ID);
+
+			if (sourcePaths != null && sourcePaths.length > 0 && sourcePaths[0] != null) {
+				return sourcePaths[0];
+			}
+
+			return generateSourceName(declaringType.getName());
+		}
+
+		return null;
+	}
+
+	private static final IStackFrame[] EMPTY_STACK = new IStackFrame[0];
+
+	private IStackFrame[] getStackFrames(Object element) throws DebugException {
+		if (element instanceof IStackFrame) {
+			IStackFrame[] frames = ((IStackFrame) element).getThread().getStackFrames();
+			for (int i = 0; i < frames.length - 1; i++) {
+				if (frames[i] == element) {
+					return Arrays.copyOfRange(frames, i + 1, frames.length - 1);
+				}
+			}
+		}
+		return EMPTY_STACK;
+	}
+
+	@Override
+	public Iterable<File> getStackFramesClassesLocations(Object element) throws DebugException {
+		IStackFrame[] stack = getStackFrames(element);
+
+		return new Iterable<File>() {
+			@Override
+			public Iterator<File> iterator() {
+				return Arrays.stream(stack) //
+						.map(frame -> getClassesLocation(frame)) //
+						.filter(frameLocation -> frameLocation != null) //
+						.iterator();
+			}
+
+			File getClassesLocation(IStackFrame frame) {
+				// TODO consider ignoring DebugException for all IJDIHeloper methods
+				try {
+					return JDIHelpers.this.getClassesLocation(frame);
+				}
+				catch (DebugException e) {
+					return null;
+				}
+			}
+		};
+	}
+
+	// copy&paste from org.eclipse.pde.internal.launching.sourcelookup.PDESourceLookupQuery.generateSourceName(String)
+	private static String generateSourceName(String qualifiedTypeName) {
+		int index = qualifiedTypeName.indexOf('$');
+		if (index >= 0) {
+			qualifiedTypeName = qualifiedTypeName.substring(0, index);
+		}
+		return qualifiedTypeName.replace('.', File.separatorChar) + ".java"; //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JDIStratumPropertyTester.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JDIStratumPropertyTester.java
new file mode 100644
index 0000000..74dc423
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JDIStratumPropertyTester.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.debug.core.DebugException;
+
+/**
+ * {@link PropertyTester} that returns {@code true} iff testee is a JDI object that has advanced source lookup JSR-45 stratum.
+ */
+public class JDIStratumPropertyTester extends PropertyTester {
+
+	@Override
+	public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+		boolean result;
+		try {
+			result = IJDIHelpers.INSTANCE.getClassesLocation(receiver) != null;
+		}
+		catch (DebugException e) {
+			result = false;
+		}
+		return result;
+	}
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JavaagentVariableResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JavaagentVariableResolver.java
new file mode 100644
index 0000000..87633f0
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/JavaagentVariableResolver.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2015-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.variables.IDynamicVariable;
+import org.eclipse.core.variables.IDynamicVariableResolver;
+
+/**
+ * {@code sourcelookup_javaagent} dynamic variable resolver.
+ */
+public class JavaagentVariableResolver implements IDynamicVariableResolver {
+	@Override
+	public String resolveValue(IDynamicVariable variable, String argument) throws CoreException {
+		return AdvancedSourceLookupSupport.getJavaagentLocation();
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/Messages.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/Messages.java
new file mode 100644
index 0000000..d79d08f
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/Messages.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2015-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.jdt.internal.launching.sourcelookup.advanced.messages"; //$NON-NLS-1$
+	public static String BackgroundProcessingJob_name;
+	public static String BackgroundProcessingJob_failed;
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/WorkspaceProjectSourceContainers.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/WorkspaceProjectSourceContainers.java
new file mode 100644
index 0000000..3bfd7f9
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/WorkspaceProjectSourceContainers.java
@@ -0,0 +1,434 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.launching.sourcelookup.advanced;
+
+import static org.eclipse.jdt.core.IJavaElementDelta.F_ADDED_TO_CLASSPATH;
+import static org.eclipse.jdt.core.IJavaElementDelta.F_CLASSPATH_CHANGED;
+import static org.eclipse.jdt.core.IJavaElementDelta.F_CLOSED;
+import static org.eclipse.jdt.core.IJavaElementDelta.F_OPENED;
+import static org.eclipse.jdt.core.IJavaElementDelta.F_REMOVED_FROM_CLASSPATH;
+import static org.eclipse.jdt.core.IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.jdt.core.ElementChangedEvent;
+import org.eclipse.jdt.core.IElementChangedListener;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IJavaModel;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.FileHashing.Hasher;
+import org.eclipse.jdt.launching.sourcelookup.advanced.IWorkspaceProjectDescriber;
+import org.eclipse.jdt.launching.sourcelookup.advanced.IWorkspaceProjectDescriber.IJavaProjectSourceDescription;
+import org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer;
+
+/**
+ * Workspace project source container factory.
+ *
+ * <p>
+ * The factory creates both project and project classpath entry containers. Both projects and project classpath entries can be identified by their
+ * filesystem location and, if the location is a file, by the file SHA1 checksum.
+ *
+ * <p>
+ * The factory maintains up-to-date registry of workspace projects and their classpath entries and can be used to create source containers fast enough
+ * to be used from UI thread.
+ */
+public class WorkspaceProjectSourceContainers {
+	private final IElementChangedListener changeListener = new IElementChangedListener() {
+		@Override
+		public void elementChanged(ElementChangedEvent event) {
+			try {
+				final Set<IJavaProject> remove = new HashSet<>();
+				final Set<IJavaProject> add = new HashSet<>();
+
+				processDelta(event.getDelta(), remove, add);
+
+				if (!remove.isEmpty() || !add.isEmpty()) {
+					AdvancedSourceLookupSupport.schedule((m) -> updateProjects(remove, add, m));
+				}
+			}
+			catch (CoreException e) {
+				// maybe do something about it?
+			}
+		}
+
+		private void processDelta(final IJavaElementDelta delta, Set<IJavaProject> remove, Set<IJavaProject> add) throws CoreException {
+			// TODO review, this looks too complicated to add/remove java projects
+
+			final IJavaElement element = delta.getElement();
+			final int kind = delta.getKind();
+			switch (element.getElementType()) {
+				case IJavaElement.JAVA_MODEL:
+					processChangedChildren(delta, remove, add);
+					break;
+				case IJavaElement.JAVA_PROJECT:
+					switch (kind) {
+						case IJavaElementDelta.REMOVED:
+							remove.add((IJavaProject) element);
+							break;
+						case IJavaElementDelta.ADDED:
+							add.add((IJavaProject) element);
+							break;
+						case IJavaElementDelta.CHANGED:
+							if ((delta.getFlags() & F_CLOSED) != 0) {
+								remove.add((IJavaProject) element);
+							} else if ((delta.getFlags() & F_OPENED) != 0) {
+								add.add((IJavaProject) element);
+							} else if ((delta.getFlags() & (F_CLASSPATH_CHANGED | F_RESOLVED_CLASSPATH_CHANGED)) != 0) {
+								remove.add((IJavaProject) element);
+								add.add((IJavaProject) element);
+							}
+							break;
+					}
+					processChangedChildren(delta, remove, add);
+					break;
+				case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+					if ((delta.getFlags() & (F_ADDED_TO_CLASSPATH | F_REMOVED_FROM_CLASSPATH)) != 0) {
+						remove.add(element.getJavaProject());
+						add.add(element.getJavaProject());
+					}
+					break;
+			}
+		}
+
+		private void processChangedChildren(IJavaElementDelta delta, Set<IJavaProject> remove, Set<IJavaProject> add) throws CoreException {
+			for (IJavaElementDelta childDelta : delta.getAffectedChildren()) {
+				processDelta(childDelta, remove, add);
+			}
+		}
+	};
+
+	private static class JavaProjectDescriptionBuilder implements IJavaProjectSourceDescription {
+		final Set<File> locations = new HashSet<>();
+		final List<Supplier<ISourceContainer>> factories = new ArrayList<>();
+		final Map<File, IPackageFragmentRoot> dependencyLocations = new HashMap<>();
+
+		@Override
+		public void addLocation(File location) {
+			locations.add(location);
+		}
+
+		@Override
+		public void addSourceContainerFactory(Supplier<ISourceContainer> factory) {
+			factories.add(factory);
+		}
+
+		@Override
+		public void addDependencies(Map<File, IPackageFragmentRoot> dependencies) {
+			// TODO decide what happens if the same location is associated with multiple package fragment roots
+			this.dependencyLocations.putAll(dependencies);
+		}
+
+	}
+
+	private static class JavaProjectDescription {
+		final Set<File> classesLocations;
+
+		final Set<Object> classesLocationsHashes;
+
+		final List<Supplier<ISourceContainer>> sourceContainerFactories;
+
+		final Map<File, IPackageFragmentRoot> dependencies;
+
+		final Map<Object, IPackageFragmentRoot> dependencyHashes;
+
+		public JavaProjectDescription(Set<File> locations, Set<Object> hashes, List<Supplier<ISourceContainer>> factories, Map<File, IPackageFragmentRoot> dependencies, Map<Object, IPackageFragmentRoot> dependencyHashes) {
+			this.classesLocations = Collections.unmodifiableSet(locations);
+			this.classesLocationsHashes = Collections.unmodifiableSet(hashes);
+			this.sourceContainerFactories = Collections.unmodifiableList(factories);
+			this.dependencies = Collections.unmodifiableMap(dependencies);
+			this.dependencyHashes = Collections.unmodifiableMap(dependencyHashes);
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj) {
+				return true;
+			}
+			if (!(obj instanceof JavaProjectDescription)) {
+				return false;
+			}
+			JavaProjectDescription other = (JavaProjectDescription) obj;
+			return classesLocations.equals(other.classesLocations);
+		}
+
+		@Override
+		public int hashCode() {
+			return classesLocations.hashCode();
+		}
+	}
+
+	/**
+	 * Guards concurrent access to {@link #locations}, {@link #hashes} and {@link #projects}. Necessary because source lookup queries and java model
+	 * changes are processed on different threads.
+	 *
+	 * @TODO consider using ConcurrentMaps instead of explicit locking.
+	 */
+	private final Object lock = new Object() {
+	};
+
+	/**
+	 * Maps project classes location to project description.
+	 */
+	private final Map<File, JavaProjectDescription> locations = new HashMap<>();
+
+	/**
+	 * Maps project dependency hash to project descriptions. Hash-based source lookup is useful when runtime uses copies of jars used by the
+	 * workspace.
+	 */
+	private final Map<Object, Collection<JavaProjectDescription>> hashes = new HashMap<>();
+
+	/**
+	 * Maps java project to project description.
+	 */
+	private final Map<IJavaProject, JavaProjectDescription> projects = new HashMap<>();
+
+	/**
+	 * Creates and returns new source containers for the workspace project identified by the given location. Returns {@code null} if there is no such
+	 * workspace project.
+	 */
+	public ISourceContainer createProjectContainer(File projectLocation) {
+		Hasher hasher = FileHashing.hasher(); // use long-lived hasher
+
+		JavaProjectDescription description = getProjectByLocation(projectLocation);
+
+		if (description == null) {
+			Collection<JavaProjectDescription> desciptions = getProjectsByHash(projectLocation, hasher);
+			if (!desciptions.isEmpty()) {
+				// it is possible, but unlikely, to have multiple binary projects for the same jar
+				description = desciptions.iterator().next();
+			}
+		}
+
+		if (description == null) {
+			return null;
+		}
+
+		List<ISourceContainer> containers = new ArrayList<>();
+		for (Supplier<ISourceContainer> factory : description.sourceContainerFactories) {
+			containers.add(factory.get());
+		}
+
+		return CompositeSourceContainer.compose(containers);
+	}
+
+	private JavaProjectDescription getProjectByLocation(File projectLocation) {
+		synchronized (lock) {
+			return locations.get(projectLocation);
+		}
+	}
+
+	private Collection<JavaProjectDescription> getProjectsByHash(File projectLocation, FileHashing.Hasher hasher) {
+		Collection<JavaProjectDescription> projects;
+		synchronized (lock) {
+			projects = hashes.get(hasher.hash(projectLocation));
+			return projects != null ? new HashSet<>(projects) : Collections.emptySet();
+		}
+	}
+
+	/**
+	 * Creates and returns new source container for the workspace project classpath entry identified by the given project and entry locations. Returns
+	 * {@code null} if there is no such project classpath entry.
+	 */
+	public ISourceContainer createClasspathEntryContainer(File projectLocation, File entryLocation) {
+		Hasher hasher = FileHashing.hasher(); // use long-lived hasher
+
+		JavaProjectDescription projectByLocation = getProjectByLocation(projectLocation);
+
+		IPackageFragmentRoot dependency = getProjectDependency(projectByLocation, entryLocation, hasher);
+
+		if (dependency == null && projectByLocation == null) {
+			for (JavaProjectDescription projectByHash : getProjectsByHash(projectLocation, hasher)) {
+				dependency = getProjectDependency(projectByHash, entryLocation, hasher);
+				if (dependency != null) {
+					break;
+				}
+			}
+		}
+
+		if (dependency == null) {
+			return null;
+		}
+
+		return new PackageFragmentRootSourceContainer(dependency);
+	}
+
+	private IPackageFragmentRoot getProjectDependency(JavaProjectDescription project, File entryLocation, FileHashing.Hasher hasher) {
+		if (project == null) {
+			return null;
+		}
+
+		IPackageFragmentRoot dependency = project.dependencies.get(entryLocation);
+
+		if (dependency == null) {
+			dependency = project.dependencyHashes.get(hasher.hash(entryLocation));
+		}
+		return dependency;
+	}
+
+	public void initialize(IProgressMonitor monitor) throws CoreException {
+		// note that initialization and java element change events are processed by the same background job
+		// this guarantees the events aren't lost when they are delivered while the initialization is running
+		JavaCore.addElementChangedListener(changeListener);
+
+		final IJavaModel javaModel = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
+		final IJavaProject[] javaProjects = javaModel.getJavaProjects();
+
+		SubMonitor progress = SubMonitor.convert(monitor, javaProjects.length);
+
+		// TODO this can take significant time for large workspaces, consider running on multiple threads
+		// NB: can't persist state across restarts because java element change events are not delivered when this plugin isn't active
+
+		Hasher hasher = FileHashing.newHasher(); // short-lived hasher for bulk workspace indexing
+
+		List<IWorkspaceProjectDescriber> describers = getJavaProjectDescribers();
+		for (IJavaProject project : javaProjects) {
+			addJavaProject(project, describers, hasher, progress.split(1));
+		}
+	}
+
+	public void close() {
+		JavaCore.removeElementChangedListener(changeListener);
+		synchronized (lock) {
+			this.locations.clear();
+			this.hashes.clear();
+			this.projects.clear();
+		}
+	}
+
+	private void addJavaProject(IJavaProject project, List<IWorkspaceProjectDescriber> describers, FileHashing.Hasher hasher, IProgressMonitor monitor) throws CoreException {
+		if (project == null) {
+			throw new IllegalArgumentException();
+		}
+
+		JavaProjectDescriptionBuilder builder = new JavaProjectDescriptionBuilder();
+
+		for (IWorkspaceProjectDescriber describer : describers) {
+			describer.describeProject(project, builder);
+		}
+
+		Set<File> locations = builder.locations;
+		List<Supplier<ISourceContainer>> factories = builder.factories;
+		Map<File, IPackageFragmentRoot> dependencies = builder.dependencyLocations;
+
+		// make binary project support little easier to implement
+		locations.forEach(location -> dependencies.remove(location));
+
+		Set<Object> hashes = new HashSet<>();
+		locations.forEach(location -> {
+			Object hash = hasher.hash(location);
+			if (hash != null) {
+				hashes.add(hash);
+			}
+		});
+
+		Map<Object, IPackageFragmentRoot> dependencyHashes = new HashMap<>();
+		dependencies.forEach((location, packageFragmentRoot) -> dependencyHashes.put(hasher.hash(location), packageFragmentRoot));
+
+		JavaProjectDescription info = new JavaProjectDescription(locations, hashes, factories, dependencies, dependencyHashes);
+
+		synchronized (this.lock) {
+			for (File location : locations) {
+				this.locations.put(location, info);
+			}
+			for (Object hash : hashes) {
+				Collection<JavaProjectDescription> hashProjects = this.hashes.get(hash);
+				if (hashProjects == null) {
+					hashProjects = new HashSet<>();
+					this.hashes.put(hash, hashProjects);
+				}
+				hashProjects.add(info);
+			}
+			this.projects.put(project, info);
+		}
+
+		SubMonitor.done(monitor);
+	}
+
+	protected List<IWorkspaceProjectDescriber> getJavaProjectDescribers() {
+		List<IWorkspaceProjectDescriber> result = new ArrayList<>();
+
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+
+		IConfigurationElement[] elements = registry.getConfigurationElementsFor(AdvancedSourceLookupSupport.ID_workspaceProjectDescribers);
+
+		for (IConfigurationElement element : elements) {
+			if ("describer".equals(element.getName())) { //$NON-NLS-1$
+				try {
+					result.add((IWorkspaceProjectDescriber) element.createExecutableExtension("class")); //$NON-NLS-1$
+				}
+				catch (CoreException e) {
+				}
+			}
+		}
+
+		result.add(new DefaultProjectDescriber());
+
+		return result;
+	}
+
+	private void removeJavaProject(IJavaProject project) {
+		if (project == null) {
+			throw new IllegalArgumentException();
+		}
+		synchronized (lock) {
+			JavaProjectDescription description = projects.remove(project);
+			if (description != null) {
+				for (File location : description.classesLocations) {
+					locations.remove(location);
+				}
+				for (Object hash : description.classesLocationsHashes) {
+					Collection<JavaProjectDescription> hashProjects = hashes.get(hash);
+					if (hashProjects != null) {
+						hashProjects.remove(description);
+						if (hashProjects.isEmpty()) {
+							hashes.remove(hash);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	void updateProjects(final Set<IJavaProject> remove, final Set<IJavaProject> add, IProgressMonitor monitor) throws CoreException {
+		SubMonitor progress = SubMonitor.convert(monitor, 1 + add.size());
+
+		progress.split(1);
+		for (IJavaProject project : remove) {
+			removeJavaProject(project);
+		}
+		List<IWorkspaceProjectDescriber> describers = getJavaProjectDescribers();
+		Hasher hasher = FileHashing.newHasher();
+		for (IJavaProject project : add) {
+			addJavaProject(project, describers, hasher, progress.split(1));
+		}
+	}
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/messages.properties b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/messages.properties
new file mode 100644
index 0000000..fcbba1c
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/sourcelookup/advanced/messages.properties
@@ -0,0 +1,13 @@
+###############################################################################
+# Copyright (c) 2015-2016 Igor Fedorenko
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#      Igor Fedorenko - initial API and implementation
+###############################################################################
+
+BackgroundProcessingJob_name=Advanced source lookup job
+BackgroundProcessingJob_failed=Advanced source lookup task failed
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
index 4712dcb..a97cc4d 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/AbstractJavaLaunchConfigurationDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,12 +9,19 @@
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.launching;
+
+import static org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport.createAdvancedLaunch;
+import static org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport.getJavaagentString;
+import static org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport.isAdvancedSourcelookupEnabled;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.eclipse.core.resources.IContainer;
@@ -39,8 +46,10 @@
 import org.eclipse.debug.core.model.IBreakpoint;
 import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
 import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
+import org.eclipse.jdt.core.IClasspathAttribute;
 import org.eclipse.jdt.core.IJavaModelMarker;
 import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
 import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
@@ -62,10 +71,13 @@
  * @since 2.0
  */
 public abstract class AbstractJavaLaunchConfigurationDelegate extends LaunchConfigurationDelegate implements IDebugEventSetListener {
+	private boolean allowAdvancedSourcelookup;
+
 	/**
 	 * A list of prerequisite projects ordered by their build order.
 	 */
 	private IProject[] fOrderedProjects;
+
 	/**
 	 * Convenience method to get the launch manager.
 	 *
@@ -419,7 +431,8 @@
 		for (IRuntimeClasspathEntry entry : entries) {
 			String location = entry.getLocation();
 			if (location != null) {
-				if (entry.getClasspathProperty() != IRuntimeClasspathEntry.MODULE_PATH) {
+				if (entry.getClasspathProperty() != IRuntimeClasspathEntry.MODULE_PATH
+						&& entry.getClasspathProperty() != IRuntimeClasspathEntry.PATCH_MODULE) {
 					if (!set.contains(location)) {
 						userEntries.add(location);
 						set.add(location);
@@ -596,6 +609,47 @@
 		}
 		return args;
 	}
+
+	/**
+	 * Returns the VM arguments specified by the given launch configuration, as a string. The returned string is empty if no VM arguments are
+	 * specified.
+	 *
+	 * @param configuration
+	 *            launch configuration
+	 * @param mode
+	 *            the mode in which to launch, one of the mode constants defined by <code>ILaunchManager</code> - <code>RUN_MODE</code> or
+	 *            <code>DEBUG_MODE</code>.
+	 * @return the VM arguments specified by the given launch configuration, possibly an empty string
+	 * @exception CoreException
+	 *                if unable to retrieve the attribute
+	 * @since 3.10
+	 */
+	public String getVMArguments(ILaunchConfiguration configuration, String mode) throws CoreException {
+		if (!isAdvancedSourcelup(mode)) {
+			return ""; //$NON-NLS-1$
+		}
+		if (!isJavaagentOptionSupported(configuration)) {
+			return ""; //$NON-NLS-1$
+		}
+		return getJavaagentString();
+	}
+
+	private boolean isJavaagentOptionSupported(ILaunchConfiguration configuration) {
+		try {
+			IVMInstall vm = JavaRuntime.computeVMInstall(configuration);
+			if (JavaRuntime.compareJavaVersions(vm, JavaCore.VERSION_1_4) > 0) {
+				return true;
+			}
+		} catch (CoreException e) {
+			LaunchingPlugin.log(e);
+		}
+		return false;
+	}
+
+	private boolean isAdvancedSourcelup(String mode) {
+		return allowAdvancedSourcelookup && ILaunchManager.DEBUG_MODE.equals(mode) && isAdvancedSourcelookupEnabled();
+	}
+
 	/**
 	 * Returns the Map of VM-specific attributes specified by the given launch
 	 * configuration, or <code>null</code> if none.
@@ -1051,4 +1105,100 @@
 		}
 		return null;
 	}
+
+	@Override
+	public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
+		if (!isAdvancedSourcelup(mode)) {
+			return null;
+		}
+		return createAdvancedLaunch(configuration, mode);
+	}
+
+	/**
+	 * Enabled advanced sourcelookup for this launch delegate. Advanced source lookup is disabled by default. This call has not effect if advanced
+	 * source lookup is disabled at workspace level, i.e. advanced source lookup will remain disabled even if this method is called for the launch
+	 * delegate instance.
+	 *
+	 * @since 3.10
+	 */
+	protected final void allowAdvancedSourcelookup() {
+		this.allowAdvancedSourcelookup = true;
+	}
+
+	/**
+	 * Returns the module-related command line options for the configuration that are needed at runtime as equivalents of those options specified by
+	 * {@link IClasspathAttribute}s of the following names:
+	 * <ul>
+	 * <li>{@link IClasspathAttribute#ADD_EXPORTS}</li>
+	 * <li>{@link IClasspathAttribute#ADD_READS}</li>
+	 * <li>{@link IClasspathAttribute#LIMIT_MODULES}</li>
+	 * <li>{@link IClasspathAttribute#PATCH_MODULE}</li>
+	 * </ul>
+	 *
+	 * @throws CoreException
+	 *
+	 * @since 3.10
+	 */
+	public String getModuleCLIOptions(ILaunchConfiguration configuration) throws CoreException {
+		String moduleCLIOptions = JavaRuntime.getModuleCLIOptions(configuration);
+
+		IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedRuntimeClasspath(configuration);
+		entries = JavaRuntime.resolveRuntimeClasspath(entries, configuration);
+		LinkedHashMap<String, String> moduleToLocations = new LinkedHashMap<>();
+
+		for (IRuntimeClasspathEntry entry : entries) {
+			String location = entry.getLocation();
+			if (location != null) {
+				if (entry.getClasspathProperty() == IRuntimeClasspathEntry.PATCH_MODULE) {
+					IJavaProject javaProject = entry.getJavaProject();
+					IModuleDescription moduleDescription = javaProject == null ? null : javaProject.getModuleDescription();
+					if (moduleDescription != null) {
+						String moduleName = moduleDescription.getElementName();
+						String locations = moduleToLocations.get(moduleName);
+						if (locations == null) {
+							moduleToLocations.put(moduleName, location);
+						} else {
+							moduleToLocations.put(moduleName, locations + File.pathSeparator + location);
+						}
+					} else {
+						// should not happen, log?
+					}
+				}
+			}
+		}
+		if (moduleToLocations.isEmpty()) {
+			return moduleCLIOptions;
+		}
+		StringBuilder sb = new StringBuilder(moduleCLIOptions);
+
+		for (Entry<String, String> entry : moduleToLocations.entrySet()) {
+			if (sb.length() > 0) {
+				sb.append(' ');
+			}
+			sb.append("--patch-module"); //$NON-NLS-1$
+			sb.append(' ');
+			sb.append(entry.getKey());
+			sb.append('=');
+			sb.append(entry.getValue());
+		}
+
+		boolean excludeTestCode = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false);
+		if (!excludeTestCode) {
+			// TODO: revisit to examine other possible solutions
+			IJavaProject project = getJavaProject(configuration);
+			if (project != null) {
+				for (String moduleName : project.determineModulesOfProjectsWithNonEmptyClasspath()) {
+					if (sb.length() > 0) {
+						sb.append(' ');
+					}
+					sb.append("--add-reads"); //$NON-NLS-1$
+					sb.append(' ');
+					sb.append(moduleName);
+					sb.append('=');
+					sb.append("ALL-UNNAMED"); //$NON-NLS-1$
+				}
+			}
+		}
+		return sb.toString();
+	}
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java
index 46d1419..5e910b6 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IJavaLaunchConfigurationConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -179,7 +179,7 @@
 	 * Launch configuration attribute key. The attribute value is an ordered list of strings which are mementos for runtime module path entries. When
 	 * unspecified, a default modulepath is generated by the dependency provider associated with a launch configuration (via the
 	 * <code>ATTR_CLASSPATH_PROVIDER</code> attribute).
-	 * 
+	 *
 	 * @since 3.10
 	 */
 	public static final String ATTR_MODULEPATH = LaunchingPlugin.getUniqueIdentifier() + ".MODULEPATH"; //$NON-NLS-1$
@@ -199,6 +199,23 @@
 	public static final String ATTR_DEFAULT_CLASSPATH = LaunchingPlugin.getUniqueIdentifier() + ".DEFAULT_CLASSPATH"; //$NON-NLS-1$
 
 	/**
+	 * Launch configuration attribute key. The value is a boolean specifying whether a default build path module cli options should be used when
+	 * launching a local Java application. When <code>false</code>, a module cli option must be specified via the <code>ATTR_MODULE_CLI_OPTIONS</code>
+	 * attribute. When <code>true</code> or unspecified, a classpath is computed by the classpath provider associated with a launch configuration.
+	 *
+	 * @since 3.10
+	 */
+	public static final String ATTR_DEFAULT_MODULE_CLI_OPTIONS = LaunchingPlugin.getUniqueIdentifier() + ".DEFAULT_MODULE_CLI_OPTIONS"; //$NON-NLS-1$
+
+	/**
+	 * Launch configuration attribute key. The value is a string with module cli options if the default is not used for launching a local Java
+	 * application.
+	 *
+	 * @since 3.10
+	 */
+	public static final String ATTR_MODULE_CLI_OPTIONS = LaunchingPlugin.getUniqueIdentifier() + ".MODULE_CLI_OPTIONS"; //$NON-NLS-1$
+
+	/**
 	 * Launch configuration attribute key. The value is an identifier of a
 	 * classpath provider extension used to compute the classpath
 	 * for a launch configuration. When unspecified, the default classpath
@@ -342,6 +359,15 @@
 	 * @since 3.7
 	 */
 	public static final String ATTR_USE_START_ON_FIRST_THREAD = LaunchingPlugin.getUniqueIdentifier() + ".ATTR_USE_START_ON_FIRST_THREAD"; //$NON-NLS-1$
+
+	/**
+	 * Launch configuration attribute key. The value is a boolean specifying whether output folders corresponding to test sources should not be added
+	 * to the runtime classpath and test dependencies should not be added to the default classpath.
+	 *
+	 * @since 3.10
+	 */
+	public static final String ATTR_EXCLUDE_TEST_CODE = LaunchingPlugin.getUniqueIdentifier() + ".ATTR_EXCLUDE_TEST_CODE"; //$NON-NLS-1$
+
 	/**
 	 * Status code indicating a launch configuration does not
 	 * specify a project when a project is required.
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
index 265c19d..64e0aa1 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry.java
@@ -97,19 +97,26 @@
 
 	/**
 	 * Classpath property identifier for entries that should appear on the module path for modular project.
-	 * 
+	 *
 	 * @since 3.10
 	 */
 	public static final int MODULE_PATH = 4;
 
 	/**
 	 * Classpath property identifier for entries that should appear on the class path for modular project.
-	 * 
+	 *
 	 * @since 3.10
 	 */
 	public static final int CLASS_PATH = 5;
 
 	/**
+	 * Classpath property identifier for entries that should appear as --patch-module argument for a modular project.
+	 *
+	 * @since 3.10
+	 */
+	public static final int PATCH_MODULE = 6;
+
+	/**
 	 * Returns this classpath entry's type. The type of a runtime classpath entry is
 	 * identified by one of the following constants:
 	 * <ul>
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry2.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry2.java
index ad33f57..24e8055 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry2.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntry2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -70,6 +70,20 @@
 	public IRuntimeClasspathEntry[] getRuntimeClasspathEntries(ILaunchConfiguration configuration) throws CoreException;
 
 	/**
+	 * Returns the classpath entries this entry is composed of, or an empty collection if this entry is not a composite entry.
+	 *
+	 * @param excludeTestCode
+	 *            true, if test code should be excluded
+	 * @return the classpath entries this entry is composed of, or an empty collection if this entry is not a composite entry
+	 * @throws CoreException
+	 *             if unable to retrieve contained entries
+	 * @since 3.10
+	 */
+	default public IRuntimeClasspathEntry[] getRuntimeClasspathEntries(boolean excludeTestCode) throws CoreException {
+		return getRuntimeClasspathEntries(null);
+	}
+
+	/**
 	 * Returns a human readable name for this classpath entry.
 	 *
 	 * @return a human readable name for this classpath entry
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntryResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntryResolver.java
index 95a86f9..036dc56 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntryResolver.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/IRuntimeClasspathEntryResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -86,12 +86,31 @@
 	public IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException;
 
 	/**
-	 * Returns a VM install associated with the given classpath entry,
-	 * or <code>null</code> if none.
+	 * Returns resolved runtime classpath entries for the given runtime classpath entry, in the context of the given Java project.
 	 *
-	 * @param entry classpath entry
+	 * @param entry
+	 *            runtime classpath entry to resolve, of type <code>VARIABLE</code> or <code>CONTAINTER</code>
+	 * @param project
+	 *            context in which the runtime classpath entry needs to be resolved
+	 * @param excludeTestCode
+	 *            when true, test code should be excluded
+	 * @return resolved entries (zero or more)
+	 * @exception CoreException
+	 *                if unable to resolve the entry
+	 * @since 3.10
+	 */
+	default public IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project, boolean excludeTestCode) throws CoreException {
+		return resolveRuntimeClasspathEntry(entry, project);
+	}
+
+	/**
+	 * Returns a VM install associated with the given classpath entry, or <code>null</code> if none.
+	 *
+	 * @param entry
+	 *            classpath entry
 	 * @return vm install associated with entry or <code>null</code> if none
-	 * @exception CoreException if unable to resolve a VM
+	 * @exception CoreException
+	 *                if unable to resolve a VM
 	 */
 	public IVMInstall resolveVMInstall(IClasspathEntry entry) throws CoreException;
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
index 43eef88..8719c84 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaLaunchDelegate.java
@@ -21,6 +21,7 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IModuleDescription;
 import org.eclipse.jdt.internal.launching.LaunchingMessages;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedJavaLaunchDelegate;
 import org.eclipse.osgi.util.NLS;
 
 /**
@@ -28,6 +29,8 @@
  * <p>
  * Clients may subclass and instantiate this class.
  * </p>
+ *
+ * @see AdvancedJavaLaunchDelegate
  * @since 3.1
  */
 public class JavaLaunchDelegate extends AbstractJavaLaunchConfigurationDelegate {
@@ -64,7 +67,7 @@
 
 			// Program & VM arguments
 			String pgmArgs = getProgramArguments(configuration);
-			String vmArgs = getVMArguments(configuration);
+			String vmArgs = concat(getVMArguments(configuration), getVMArguments(configuration, mode));
 			ExecutionArguments execArgs = new ExecutionArguments(vmArgs, pgmArgs);
 
 			// VM-specific attributes
@@ -100,6 +103,11 @@
 			} else {
 				// module path
 				runConfig.setModulepath(paths[1]);
+				if (!configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true)) {
+					runConfig.setOverrideDependencies(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MODULE_CLI_OPTIONS, "")); //$NON-NLS-1$
+				} else {
+					runConfig.setOverrideDependencies(getModuleCLIOptions(configuration));
+				}
 			}
 
 			// check for cancellation
@@ -131,4 +139,15 @@
 		}
 	}
 
+	private static String concat(String args1, String args2) {
+		StringBuilder args = new StringBuilder();
+		if (args1 != null && !args1.isEmpty()) {
+			args.append(args1);
+		}
+		if (args2 != null && !args2.isEmpty()) {
+			args.append(" "); //$NON-NLS-1$
+			args.append(args2);
+		}
+		return args.toString();
+	}
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
index 4f8e16a..b43347b 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
@@ -23,6 +23,8 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
@@ -495,11 +497,15 @@
 	 * 			VM was set or when the default VM has been disposed.
 	 */
 	public static IVMInstall getDefaultVMInstall() {
+
 		IVMInstall install= getVMFromCompositeId(getDefaultVMId());
 		if (install != null) {
 			File location = install.getInstallLocation();
 			if (location != null) {
 				if (location.exists()) {
+					if (LaunchingPlugin.isVMLogging()) {
+						LaunchingPlugin.log(LaunchingMessages.VMLogging_3 + install.getInstallLocation());
+					}
 					return install;
 				}
 			}
@@ -513,7 +519,11 @@
 			fgVMTypes = null;
 			initializeVMs();
 		}
-		return getVMFromCompositeId(getDefaultVMId());
+		install = getVMFromCompositeId(getDefaultVMId());
+		if (LaunchingPlugin.isVMLogging()) {
+			LaunchingPlugin.log(LaunchingMessages.VMLogging_3 + install.getInstallLocation());
+		}
+		return install;
 	}
 
 	/**
@@ -683,6 +693,25 @@
 	}
 
 	/**
+	 * Returns a new runtime classpath entry for the given archive(possibly external).
+	 *
+	 * @param path
+	 *            absolute path to an archive
+	 * @param classpathProperty
+	 *            the type of entry - one of <code>USER_CLASSES</code>, <code>BOOTSTRAP_CLASSES</code>,<code>STANDARD_CLASSES</code>,
+	 *            <code>MODULE_PATH</code>, <code>CLASS_PATH</code> or <code>PATCH_MODULE</code>
+	 * @param javaProject
+	 *            the javaProject to be returned by {@link IRuntimeClasspathEntry#getJavaProject()}, required for PATCH_MODULE
+	 * @return runtime classpath entry
+	 * @since 3.10
+	 */
+	public static IRuntimeClasspathEntry newArchiveRuntimeClasspathEntry(IPath path, int classpathProperty, IJavaProject javaProject) {
+		RuntimeClasspathEntry entry = new RuntimeClasspathEntry(JavaCore.newLibraryEntry(path, null, null), classpathProperty);
+		entry.setJavaProject(javaProject);
+		return entry;
+	}
+
+	/**
 	 * Returns a new runtime classpath entry for the given archive (possibly
 	 * external).
 	 *
@@ -839,16 +868,34 @@
 	}
 
 	/**
-	 * Computes and returns the default unresolved runtime classpath for the
-	 * given project.
+	 * Computes and returns the default unresolved runtime classpath for the given project.
 	 *
-	 * @param project the {@link IJavaProject} to compute the unresolved runtime classpath for
+	 * @param project
+	 *            the {@link IJavaProject} to compute the unresolved runtime classpath for
 	 * @return runtime classpath entries
-	 * @exception CoreException if unable to compute the runtime classpath
+	 * @exception CoreException
+	 *                if unable to compute the runtime classpath
 	 * @see IRuntimeClasspathEntry
 	 * @since 2.0
 	 */
 	public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeClasspath(IJavaProject project) throws CoreException {
+		return computeUnresolvedRuntimeClasspath(project, false);
+	}
+
+	/**
+	 * Computes and returns the default unresolved runtime classpath for the given project.
+	 *
+	 * @param project
+	 *            the {@link IJavaProject} to compute the unresolved runtime classpath for
+	 * @param excludeTestCode
+	 *            if true, output folders corresponding to test sources and test dependencies are excluded
+	 * @return runtime classpath entries
+	 * @exception CoreException
+	 *                if unable to compute the runtime classpath
+	 * @see IRuntimeClasspathEntry
+	 * @since 3.10
+	 */
+	public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeClasspath(IJavaProject project, boolean excludeTestCode) throws CoreException {
 		IClasspathEntry[] entries = project.getRawClasspath();
 		List<IRuntimeClasspathEntry> classpathEntries = new ArrayList<>(3);
 		for (int i = 0; i < entries.length; i++) {
@@ -897,12 +944,29 @@
 	 * @since 3.10
 	 */
 	public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeDependencies(IJavaProject project) throws CoreException {
+		return computeUnresolvedRuntimeDependencies(project, false);
+	}
+
+	/**
+	 * Computes and returns the default unresolved runtime classpath and modulepath for the given project.
+	 *
+	 * @param project
+	 *            the {@link IJavaProject} to compute the unresolved runtime classpath and modulepath for
+	 * @param excludeTestCode
+	 *            if true, output folders corresponding to test sources and test dependencies are excluded
+	 * @return runtime classpath and modulepath entries
+	 * @exception CoreException
+	 *                if unable to compute the runtime classpath and/or modulepath
+	 * @see IRuntimeClasspathEntry
+	 * @since 3.10
+	 */
+	public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeDependencies(IJavaProject project, boolean excludeTestCode) throws CoreException {
 		List<IRuntimeClasspathEntry> classpathEntries = new ArrayList<>(3);
 		if (!(project instanceof JavaProject)) {
 			return classpathEntries.toArray(new IRuntimeClasspathEntry[classpathEntries.size()]);
 		}
 		JavaProject javaProject = (JavaProject) project;
-		IClasspathEntry[] entries = javaProject.getExpandedClasspath();
+		IClasspathEntry[] entries = javaProject.getExpandedClasspath(excludeTestCode);
 
 		IClasspathEntry entry1 = JavaCore.newProjectEntry(project.getProject().getFullPath());
 		if (isModularProject(project)) {
@@ -1035,25 +1099,40 @@
 	 * @since 3.10
 	 */
 	public static boolean isModularJava(IVMInstall vm) {
+		if (compareJavaVersions(vm, JavaCore.VERSION_1_8) > 0) {
+			return true;
+		}
+		return false;
+	}
 
+	/**
+	 * Compares the version of vm and a version of the Java platform.
+	 *
+	 * @param vm
+	 *            IVMInstall to be compared
+	 * @param ver
+	 *            version to be compared
+	 * @return the value {@code 0} if both versions are the same; a value less than {@code 0} if <code>vm</code> is smaller than <code>ver</code>; and
+	 *         a value greater than {@code 0} if <code>vm</code> is higher than <code>ver</code>; a value {@code -1} in case of any exceptions;
+	 *
+	 * @since 3.10
+	 */
+	public static int compareJavaVersions(IVMInstall vm, String ver) {
 		if (vm instanceof AbstractVMInstall) {
 			AbstractVMInstall install = (AbstractVMInstall) vm;
 			String vmver = install.getJavaVersion();
-			// versionToJdkLevel only handles 3 char versions = 1.5, 1.6, 1.7, etc
 			if (vmver == null) {
-				return false;
+				return -1;
 			}
+			// versionToJdkLevel only handles 3 char versions = 1.5, 1.6, 1.7, etc
 			if (vmver.length() > 3) {
 				vmver = vmver.substring(0, 3);
 			}
-			if (JavaCore.compareJavaVersions(vmver, JavaCore.VERSION_1_8) > 0) {
-				return true;
-			}
+			return JavaCore.compareJavaVersions(vmver, ver);
 		}
-		return false;
+		return -1;
 
 	}
-
 	/**
 	 * Checks if project entry is modular
 	 *
@@ -1171,6 +1250,7 @@
 	 * @since 2.0
 	 */
 	public static IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, ILaunchConfiguration configuration) throws CoreException {
+		boolean excludeTestCode = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false);
 		switch (entry.getType()) {
 			case IRuntimeClasspathEntry.PROJECT:
 				// if the project has multiple output locations, they must be returned
@@ -1181,7 +1261,7 @@
 					if (project == null || !p.isOpen() || !project.exists()) {
 						return new IRuntimeClasspathEntry[0];
 					}
-					IRuntimeClasspathEntry[] entries = resolveOutputLocations(project, entry.getClasspathProperty());
+					IRuntimeClasspathEntry[] entries = resolveOutputLocations(project, entry.getClasspathProperty(), excludeTestCode);
 					if (entries != null) {
 						return entries;
 					}
@@ -1195,7 +1275,7 @@
 			case IRuntimeClasspathEntry.VARIABLE:
 				IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
 				if (resolver == null) {
-					IRuntimeClasspathEntry[] resolved = resolveVariableEntry(entry, null, configuration);
+					IRuntimeClasspathEntry[] resolved = resolveVariableEntry(entry, null, false, configuration);
 					if (resolved != null) {
 						return resolved;
 					}
@@ -1205,7 +1285,7 @@
 			case IRuntimeClasspathEntry.CONTAINER:
 				resolver = getContainerResolver(entry.getVariableName());
 				if (resolver == null) {
-					return computeDefaultContainerEntries(entry, configuration);
+					return computeDefaultContainerEntries(entry, configuration, excludeTestCode);
 				}
 				return resolver.resolveRuntimeClasspathEntry(entry, configuration);
 			case IRuntimeClasspathEntry.ARCHIVE:
@@ -1242,16 +1322,21 @@
 	}
 
 	/**
-	 * Default resolution for a classpath variable - resolve to an archive. Only
-	 * one of project/configuration can be non-null.
+	 * Default resolution for a classpath variable - resolve to an archive. Only one of project/configuration can be non-null.
 	 *
-	 * @param entry the {@link IRuntimeClasspathEntry} to try and resolve
-	 * @param project the project context or <code>null</code>
-	 * @param configuration configuration context or <code>null</code>
+	 * @param entry
+	 *            the {@link IRuntimeClasspathEntry} to try and resolve
+	 * @param project
+	 *            the project context or <code>null</code>
+	 * @param excludeTestCode
+	 *            if true, exclude test-code (only used if project is non-null)
+	 * @param configuration
+	 *            configuration context or <code>null</code>
 	 * @return IRuntimeClasspathEntry[]
-	 * @throws CoreException if a problem is encountered trying to resolve the given classpath entry
+	 * @throws CoreException
+	 *             if a problem is encountered trying to resolve the given classpath entry
 	 */
-	private static IRuntimeClasspathEntry[] resolveVariableEntry(IRuntimeClasspathEntry entry, IJavaProject project, ILaunchConfiguration configuration) throws CoreException {
+	private static IRuntimeClasspathEntry[] resolveVariableEntry(IRuntimeClasspathEntry entry, IJavaProject project, boolean excludeTestCode, ILaunchConfiguration configuration) throws CoreException {
 		// default resolution - an archive
 		IPath archPath = JavaCore.getClasspathVariable(entry.getVariableName());
 		if (archPath != null) {
@@ -1284,7 +1369,7 @@
 				IRuntimeClasspathEntry runtimeArchEntry = newRuntimeClasspathEntry(archEntry);
 				runtimeArchEntry.setClasspathProperty(entry.getClasspathProperty());
 				if (configuration == null) {
-					return resolveRuntimeClasspathEntry(runtimeArchEntry, project);
+					return resolveRuntimeClasspathEntry(runtimeArchEntry, project, excludeTestCode);
 				}
 				return resolveRuntimeClasspathEntry(runtimeArchEntry, configuration);
 			}
@@ -1293,17 +1378,23 @@
 	}
 
 	/**
-	 * Returns runtime classpath entries corresponding to the output locations
-	 * of the given project, or null if the project only uses the default
+	 * Returns runtime classpath entries corresponding to the output locations of the given project, or null if the project only uses the default
 	 * output location.
 	 *
-	 * @param project the {@link IJavaProject} to resolve the output locations for
-	 * @param classpathProperty the type of classpath entries to create
+	 * @param project
+	 *            the {@link IJavaProject} to resolve the output locations for
+	 * @param classpathProperty
+	 *            the type of classpath entries to create
+	 * @param excludeTestCode
+	 *            if true, output folders corresponding to test sources are excluded
+	 *
 	 * @return IRuntimeClasspathEntry[] or <code>null</code>
-	 * @throws CoreException if output resolution encounters a problem
+	 * @throws CoreException
+	 *             if output resolution encounters a problem
 	 */
-	private static IRuntimeClasspathEntry[] resolveOutputLocations(IJavaProject project, int classpathProperty) throws CoreException {
+	private static IRuntimeClasspathEntry[] resolveOutputLocations(IJavaProject project, int classpathProperty, boolean excludeTestCode) throws CoreException {
 		List<IPath> nonDefault = new ArrayList<>();
+		boolean defaultUsedByNonTest = false;
 		if (project.exists() && project.getProject().isOpen()) {
 			IClasspathEntry entries[] = project.getRawClasspath();
 			for (int i = 0; i < entries.length; i++) {
@@ -1311,28 +1402,47 @@
 				if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
 					IPath path = classpathEntry.getOutputLocation();
 					if (path != null) {
-						nonDefault.add(path);
+						if (!(excludeTestCode && classpathEntry.isTest())) {
+							nonDefault.add(path);
+						}
+					} else {
+						if (!classpathEntry.isTest()) {
+							defaultUsedByNonTest = true;
+						}
 					}
 				}
 			}
 		}
-		if (nonDefault.isEmpty()) {
+		boolean isModular = project.getModuleDescription() != null;
+		if (nonDefault.isEmpty() && !isModular && !excludeTestCode) {
+			// return here only if non-modular, because patch-module might be needed otherwise
 			return null;
 		}
 		// add the default location if not already included
 		IPath def = project.getOutputLocation();
-		if (!nonDefault.contains(def)) {
-			nonDefault.add(def);
+		if (!excludeTestCode || defaultUsedByNonTest) {
+			if (!nonDefault.contains(def)) {
+				nonDefault.add(def);
+			}
 		}
 		IRuntimeClasspathEntry[] locations = new IRuntimeClasspathEntry[nonDefault.size()];
 		for (int i = 0; i < locations.length; i++) {
 			IClasspathEntry newEntry = JavaCore.newLibraryEntry(nonDefault.get(i), null, null);
 			locations[i] = new RuntimeClasspathEntry(newEntry);
-			locations[i].setClasspathProperty(classpathProperty);
+			if (isModular && !containsModuleInfo(locations[i])) {
+				locations[i].setClasspathProperty(IRuntimeClasspathEntry.PATCH_MODULE);
+				((RuntimeClasspathEntry) locations[i]).setJavaProject(project);
+			} else {
+				locations[i].setClasspathProperty(classpathProperty);
+			}
 		}
 		return locations;
 	}
 
+	private static boolean containsModuleInfo(IRuntimeClasspathEntry entry) {
+		return new File(entry.getLocation() + File.separator + "module-info.class").exists(); //$NON-NLS-1$
+	}
+
 	/**
 	 * Returns resolved entries for the given entry in the context of the given
 	 * Java project. If the entry is of kind
@@ -1356,6 +1466,34 @@
 	 * @since 2.0
 	 */
 	public static IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
+		return resolveRuntimeClasspathEntry(entry, project, false);
+	}
+
+	/**
+	 * Returns resolved entries for the given entry in the context of the given
+	 * Java project. If the entry is of kind
+	 * <code>VARIABLE</code> or <code>CONTAINER</code>, variable and container
+	 * resolvers are consulted. If the entry is of kind <code>PROJECT</code>,
+	 * and the associated Java project specifies non-default output locations,
+	 * the corresponding output locations are returned. Otherwise, the given
+	 * entry is returned.
+	 * <p>
+	 * If the given entry is a variable entry, and a resolver is not registered,
+	 * the entry itself is returned. If the given entry is a container, and a
+	 * resolver is not registered, resolved runtime classpath entries are calculated
+	 * from the associated container classpath entries, in the context of the
+	 * given project.
+	 * </p>
+	 * @param entry runtime classpath entry
+	 * @param project Java project context
+	 * @param excludeTestCode
+	 *            if true, output folders corresponding to test sources and test dependencies are excluded
+	 * @return resolved runtime classpath entry
+	 * @exception CoreException if unable to resolve
+	 * @see IRuntimeClasspathEntryResolver
+	 * @since 3.10
+	 */
+	public static IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project, boolean excludeTestCode) throws CoreException {
 		switch (entry.getType()) {
 			case IRuntimeClasspathEntry.PROJECT:
 				// if the project has multiple output locations, they must be returned
@@ -1364,7 +1502,7 @@
 					IProject p = (IProject)resource;
 					IJavaProject jp = JavaCore.create(p);
 					if (jp != null && p.isOpen() && jp.exists()) {
-						IRuntimeClasspathEntry[] entries = resolveOutputLocations(jp, entry.getClasspathProperty());
+						IRuntimeClasspathEntry[] entries = resolveOutputLocations(jp, entry.getClasspathProperty(), excludeTestCode);
 						if (entries != null) {
 							return entries;
 						}
@@ -1376,22 +1514,22 @@
 			case IRuntimeClasspathEntry.VARIABLE:
 				IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
 				if (resolver == null) {
-					IRuntimeClasspathEntry[] resolved = resolveVariableEntry(entry, project, null);
+					IRuntimeClasspathEntry[] resolved = resolveVariableEntry(entry, project, excludeTestCode, null);
 					if (resolved != null) {
 						return resolved;
 					}
 					break;
 				}
-				return resolver.resolveRuntimeClasspathEntry(entry, project);
+				return resolver.resolveRuntimeClasspathEntry(entry, project, excludeTestCode);
 			case IRuntimeClasspathEntry.CONTAINER:
 				resolver = getContainerResolver(entry.getVariableName());
 				if (resolver == null) {
-					return computeDefaultContainerEntries(entry, project);
+					return computeDefaultContainerEntries(entry, project, excludeTestCode);
 				}
-				return resolver.resolveRuntimeClasspathEntry(entry, project);
+				return resolver.resolveRuntimeClasspathEntry(entry, project, excludeTestCode);
 			case IRuntimeClasspathEntry.OTHER:
 				resolver = getContributedResolver(((IRuntimeClasspathEntry2)entry).getTypeId());
-				return resolver.resolveRuntimeClasspathEntry(entry, project);
+				return resolver.resolveRuntimeClasspathEntry(entry, project, excludeTestCode);
 			default:
 				break;
 		}
@@ -1399,30 +1537,40 @@
 	}
 
 	/**
-	 * Performs default resolution for a container entry.
-	 * Delegates to the Java model.
-	 * @param entry the {@link IRuntimeClasspathEntry} to compute default container entries for
-	 * @param config the backing {@link ILaunchConfiguration}
+	 * Performs default resolution for a container entry. Delegates to the Java model.
+	 *
+	 * @param entry
+	 *            the {@link IRuntimeClasspathEntry} to compute default container entries for
+	 * @param config
+	 *            the backing {@link ILaunchConfiguration}
+	 * @param excludeTestCode
+	 *            if true, output folders corresponding to test sources and test dependencies are excluded
 	 * @return the complete listing of default container entries or an empty list, never <code>null</code>
-	 * @throws CoreException if the computation encounters a problem
+	 * @throws CoreException
+	 *             if the computation encounters a problem
 	 */
-	private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, ILaunchConfiguration config) throws CoreException {
+	private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, ILaunchConfiguration config, boolean excludeTestCode) throws CoreException {
 		IJavaProject project = entry.getJavaProject();
 		if (project == null) {
 			project = getJavaProject(config);
 		}
-		return computeDefaultContainerEntries(entry, project);
+		return computeDefaultContainerEntries(entry, project, excludeTestCode);
 	}
 
 	/**
-	 * Performs default resolution for a container entry.
-	 * Delegates to the Java model.
-	 * @param entry the {@link IRuntimeClasspathEntry} to compute default container entries for
-	 * @param project the backing {@link IJavaProject}
+	 * Performs default resolution for a container entry. Delegates to the Java model.
+	 *
+	 * @param entry
+	 *            the {@link IRuntimeClasspathEntry} to compute default container entries for
+	 * @param project
+	 *            the backing {@link IJavaProject}
+	 * @param excludeTestCode
+	 *            if true, output folders corresponding to test sources and test dependencies are excluded
 	 * @return the complete listing of default container entries or an empty list, never <code>null</code>
-	 * @throws CoreException if the computation encounters a problem
+	 * @throws CoreException
+	 *             if the computation encounters a problem
 	 */
-	private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
+	private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, IJavaProject project, boolean excludeTestCode) throws CoreException {
 		if (project == null || entry == null) {
 			// cannot resolve without entry or project context
 			return new IRuntimeClasspathEntry[0];
@@ -1466,7 +1614,7 @@
 					if (!projects.contains(jp)) {
 						projects.add(jp);
 						IRuntimeClasspathEntry classpath = newDefaultProjectClasspathEntry(jp);
-						IRuntimeClasspathEntry[] entries = resolveRuntimeClasspathEntry(classpath, jp);
+						IRuntimeClasspathEntry[] entries = resolveRuntimeClasspathEntry(classpath, jp, excludeTestCode);
 						for (int j = 0; j < entries.length; j++) {
 							IRuntimeClasspathEntry e = entries[j];
 							if (!resolved.contains(e)) {
@@ -1533,7 +1681,8 @@
 							IJavaProject project = JavaRuntime.getJavaProject(configuration);
 							if (project == null) {
 								entries2.add(entry);
-							} else {
+							}
+							else {
 								IPackageFragmentRoot root = project.findPackageFragmentRoot(entry.getPath());
 								if (root == null && !entry.getPath().lastSegment().contains("jrt-fs.jar")) { //$NON-NLS-1$
 									entries2.add(entry);
@@ -3236,4 +3385,131 @@
 		}
 		throw new CoreException(status);
 	}
+
+	private static final String BLANK = " "; //$NON-NLS-1$
+	private static final String COMMA = ","; //$NON-NLS-1$
+	private static final String OPTION_START = "--"; //$NON-NLS-1$
+	private static final String ADD_MODULES = "--add-modules "; //$NON-NLS-1$
+	private static final String LIMIT_MODULES = "--limit-modules "; //$NON-NLS-1$
+
+	/**
+	 * Returns the module-related command line options for the configuration that are needed at runtime as equivalents of those options specified by
+	 * {@link IClasspathAttribute}s of the following names:
+	 * <ul>
+	 * <li>{@link IClasspathAttribute#ADD_EXPORTS}</li>
+	 * <li>{@link IClasspathAttribute#ADD_READS}</li>
+	 * <li>{@link IClasspathAttribute#LIMIT_MODULES}</li>
+	 * <li>{@link IClasspathAttribute#PATCH_MODULE}</li>
+	 * </ul>
+	 *
+	 * @since 3.10
+	 */
+	public static String getModuleCLIOptions(ILaunchConfiguration configuration) {
+		StringBuilder cliOptionString = new StringBuilder();
+		try {
+			IRuntimeClasspathEntry[] entries;
+			entries = JavaRuntime.computeUnresolvedRuntimeClasspath(configuration);
+
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+			for (IRuntimeClasspathEntry iRuntimeClasspathEntry : entries) {
+				IClasspathEntry classpathEntry = iRuntimeClasspathEntry.getClasspathEntry();
+				if (classpathEntry != null && classpathEntry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+					IResource res = root.findMember(classpathEntry.getPath());
+					IJavaProject jp = (IJavaProject) JavaCore.create(res);
+					IClasspathEntry[] rawClasspath = jp.getRawClasspath();
+					for (IClasspathEntry iClasspathEntry : rawClasspath) {
+						if (iClasspathEntry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+							if (JavaRuntime.JRE_CONTAINER.equals(iClasspathEntry.getPath().segment(0))) {
+								String cliOptions = getModuleCLIOptions(jp, iClasspathEntry);
+								if (cliOptionString.length() > 0 && cliOptions.length() > 0) {
+									cliOptionString.append(" "); //$NON-NLS-1$
+								}
+								cliOptionString.append(cliOptions);
+							}
+						}
+					}
+
+				}
+			}
+		}
+		catch (CoreException e) {
+			e.printStackTrace();
+		}
+		return cliOptionString.toString().trim();
+	}
+
+	/**
+	 * Returns the module-related command line options that are needed at runtime as equivalents of those options specified by
+	 * {@link IClasspathAttribute}s of the following names:
+	 * <ul>
+	 * <li>{@link IClasspathAttribute#ADD_EXPORTS}</li>
+	 * <li>{@link IClasspathAttribute#ADD_READS}</li>
+	 * <li>{@link IClasspathAttribute#LIMIT_MODULES}</li>
+	 * </ul>
+	 * <p>
+	 * Note that the {@link IClasspathAttribute#LIMIT_MODULES} value may be split into an {@code --add-modules} part and a {@code --limit-modules}
+	 * part.
+	 * </p>
+	 *
+	 * @param project
+	 *            the project holding the main class to be launched
+	 * @param systemLibrary
+	 *            the classpath entry of the given project which represents the JRE System Library
+	 * @return module-related command line options suitable for running the application.
+	 * @throws JavaModelException
+	 *             when access to the classpath or module description of the given project fails.
+	 */
+	private static String getModuleCLIOptions(IJavaProject project, IClasspathEntry systemLibrary) throws JavaModelException {
+		StringBuilder buf = new StringBuilder();
+		for (IClasspathEntry classpathEntry : project.getRawClasspath()) {
+			for (IClasspathAttribute classpathAttribute : classpathEntry.getExtraAttributes()) {
+				String optName = classpathAttribute.getName();
+				switch (optName) {
+					case IClasspathAttribute.ADD_EXPORTS:
+					case IClasspathAttribute.ADD_READS:
+						for (String value : classpathAttribute.getValue().split(COMMA)) {
+							buf.append(OPTION_START).append(optName).append(BLANK).append(value).append(BLANK);
+						}
+						break;
+					case IClasspathAttribute.LIMIT_MODULES:
+						addLimitModules(buf, project, systemLibrary, classpathAttribute.getValue());
+						break;
+				}
+			}
+		}
+		return buf.toString().trim();
+	}
+
+	private static void addLimitModules(StringBuilder buf, IJavaProject prj, IClasspathEntry systemLibrary, String value) throws JavaModelException {
+		String[] modules = value.split(COMMA);
+		boolean isUnnamed = prj.getModuleDescription() == null;
+		if (isUnnamed) {
+			Set<String> selected = new HashSet<>(Arrays.asList(modules));
+			List<IPackageFragmentRoot> allSystemRoots = Arrays.asList(prj.findUnfilteredPackageFragmentRoots(systemLibrary));
+			Set<String> defaultModules = new HashSet<>(JavaProject.defaultRootModules(allSystemRoots));
+
+			Set<String> limit = new HashSet<>(defaultModules);
+			if (limit.retainAll(selected)) { // limit = selected ∩ default -- only add the option, if limit ⊂ default
+				if (limit.isEmpty()) {
+					throw new IllegalArgumentException("Cannot hide all modules, at least java.base is required"); //$NON-NLS-1$
+				}
+				buf.append(LIMIT_MODULES).append(joinedSortedList(limit)).append(BLANK);
+			}
+
+			Set<String> add = new HashSet<>(selected);
+			add.removeAll(defaultModules);
+			if (!add.isEmpty()) { // add = selected \ default
+				buf.append(ADD_MODULES).append(joinedSortedList(add)).append(BLANK);
+			}
+		} else {
+			Arrays.sort(modules);
+			buf.append(LIMIT_MODULES).append(String.join(COMMA, modules)).append(BLANK);
+		}
+	}
+
+	private static String joinedSortedList(Collection<String> list) {
+		String[] limitArray = list.toArray(new String[list.size()]);
+		Arrays.sort(limitArray);
+		return String.join(COMMA, limitArray);
+	}
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardClasspathProvider.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardClasspathProvider.java
index 396ee7f..715b639 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardClasspathProvider.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardClasspathProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -38,6 +38,7 @@
 	public IRuntimeClasspathEntry[] computeUnresolvedClasspath(ILaunchConfiguration configuration) throws CoreException {
 		boolean useDefault = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, true);
 		boolean isModular = JavaRuntime.isModularConfiguration(configuration);
+		boolean excludeTestCode = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_EXCLUDE_TEST_CODE, false);
 		if (useDefault) {
 			IJavaProject proj = JavaRuntime.getJavaProject(configuration);
 			IRuntimeClasspathEntry jreEntry = JavaRuntime.computeJREEntry(configuration);
@@ -50,9 +51,9 @@
 			}
 			IRuntimeClasspathEntry[] entries = null;
 			if (isModular) {
-				entries = JavaRuntime.computeUnresolvedRuntimeDependencies(proj);
+				entries = JavaRuntime.computeUnresolvedRuntimeDependencies(proj, excludeTestCode);
 			} else {
-				entries = JavaRuntime.computeUnresolvedRuntimeClasspath(proj);
+				entries = JavaRuntime.computeUnresolvedRuntimeClasspath(proj, excludeTestCode);
 			}
 			// replace project JRE with config's JRE
 			IRuntimeClasspathEntry projEntry = isModular ? JavaRuntime.computeModularJREEntry(proj) : JavaRuntime.computeJREEntry(proj);
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java
index 390bd5d..bd86a0a 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/VMRunnerConfiguration.java
@@ -34,6 +34,7 @@
 	private String[] fModulepath;
 	private String fModuleDescription;
 	private String fWorkingDirectory;
+	private String fOverrideDependencies;
 	private Map<String, Object> fVMSpecificAttributesMap;
 	private boolean fResume = true;
 
@@ -308,4 +309,26 @@
 	public String getModuleDescription() {
 		return this.fModuleDescription;
 	}
+
+	/**
+	 * Gets the fOverrideDependencies.
+	 * 
+	 * @return the fOverrideDependencies
+	 * @since 3.10
+	 */
+	public String getOverrideDependencies() {
+		return fOverrideDependencies;
+	}
+
+	/**
+	 * Sets the fOverrideDependencies.
+	 * 
+	 * @param fOverrideDependencies
+	 *            the fOverrideDependencies to set
+	 * @since 3.10
+	 */
+	public void setOverrideDependencies(String fOverrideDependencies) {
+		this.fOverrideDependencies = fOverrideDependencies;
+	}
+
 }
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedJavaLaunchDelegate.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedJavaLaunchDelegate.java
new file mode 100644
index 0000000..583038d
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedJavaLaunchDelegate.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.launching.sourcelookup.advanced;
+
+import org.eclipse.jdt.launching.JavaLaunchDelegate;
+
+/**
+ * A launch delegate for launching local Java applications with advanced source lookup support.
+ *
+ * @since 3.10
+ * @provisional This is part of work in progress and can be changed, moved or removed without notice
+ */
+public class AdvancedJavaLaunchDelegate extends JavaLaunchDelegate {
+
+	public AdvancedJavaLaunchDelegate() {
+		allowAdvancedSourcelookup();
+	}
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookup.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookup.java
new file mode 100644
index 0000000..9c40b56
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookup.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.launching.sourcelookup.advanced;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.IPersistableSourceLocator;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.IJDIHelpers;
+
+/**
+ * Static methods for implementing advanced source lookup.
+ *
+ * @since 3.10
+ * @provisional This is part of work in progress and can be changed, moved or removed without notice
+ */
+public class AdvancedSourceLookup {
+	private static final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+
+	/**
+	 * Returns {@code true} if the given project has sources folders, {@code false} otherwise.
+	 */
+	public static boolean isSourceProject(IJavaProject project) throws JavaModelException {
+		for (IPackageFragmentRoot fragment : project.getPackageFragmentRoots()) {
+			if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public static Map<File, IPackageFragmentRoot> getClasspath(IJavaProject project) throws JavaModelException {
+		final Map<File, IPackageFragmentRoot> classpath = new LinkedHashMap<>();
+		for (IPackageFragmentRoot fragment : project.getPackageFragmentRoots()) {
+			if (fragment.getKind() == IPackageFragmentRoot.K_BINARY) {
+				File classpathLocation;
+				if (fragment.isExternal()) {
+					classpathLocation = fragment.getPath().toFile();
+				} else {
+					classpathLocation = fragment.getResource().getLocation().toFile();
+				}
+				classpath.put(classpathLocation, fragment);
+			}
+		}
+		return classpath;
+	}
+
+	public static Set<File> getOutputDirectories(IJavaProject project) throws JavaModelException {
+		final Set<File> locations = new LinkedHashSet<>();
+		addWorkspaceLocation(locations, project.getOutputLocation());
+		for (IClasspathEntry cpe : project.getRawClasspath()) {
+			if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE && cpe.getOutputLocation() != null) {
+				addWorkspaceLocation(locations, cpe.getOutputLocation());
+			}
+		}
+		return locations;
+	}
+
+	private static void addWorkspaceLocation(Collection<File> locations, IPath workspacePath) {
+		IResource resource = root.findMember(workspacePath);
+		if (resource != null) {
+			locations.add(resource.getLocation().toFile());
+		}
+	}
+
+	/**
+	 * Returns {@code -javaagent} jvm launch argument.
+	 */
+	public static String getJavaagentString() {
+		return AdvancedSourceLookupSupport.getJavaagentString();
+	}
+
+	/**
+	 * Returns filesystem classes location that corresponds to the given debug element, or {@code null} if the location cannot be determined.
+	 */
+	public static File getClassesLocation(Object fElement) throws DebugException {
+		return IJDIHelpers.INSTANCE.getClassesLocation(fElement);
+	}
+
+	/**
+	 * Creates and returns new {@link IPersistableSourceLocator} of the specified type and with the provided configuration.
+	 */
+	public static IPersistableSourceLocator createSourceLocator(String type, ILaunchConfiguration configuration) throws CoreException {
+		return AdvancedSourceLookupSupport.createSourceLocator(type, configuration);
+	}
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookupParticipant.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookupParticipant.java
new file mode 100644
index 0000000..59a7cc1
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/AdvancedSourceLookupParticipant.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.launching.sourcelookup.advanced;
+
+import static org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport.getContextMonitor;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.model.DebugElement;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.CompositeSourceContainer;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.IJDIHelpers;
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.WorkspaceProjectSourceContainers;
+
+/**
+ * @since 3.10
+ * @provisional This is part of work in progress and can be changed, moved or removed without notice
+ */
+public class AdvancedSourceLookupParticipant implements ISourceLookupParticipant {
+
+	private final IJDIHelpers jdi;
+
+	private ISourceLookupDirector director;
+
+	private final Map<File, ISourceContainer> containers = new HashMap<>();
+
+	public AdvancedSourceLookupParticipant() {
+		this(IJDIHelpers.INSTANCE);
+	}
+
+	/**
+	 * @noreference this constructor is visible for test purposes only
+	 */
+	public AdvancedSourceLookupParticipant(IJDIHelpers jdi) {
+		this.jdi = jdi;
+	}
+
+	@Override
+	public void init(ISourceLookupDirector director) {
+		this.director = director;
+	}
+
+	@Override
+	public Object[] findSourceElements(Object element) throws CoreException {
+		ISourceContainer container = getSourceContainer(element, false /* don't refresh cache */, null /* async */ );
+
+		if (container == null) {
+			return null;
+		}
+
+		String sourcePath = jdi.getSourcePath(element);
+		if (sourcePath == null) {
+			// can't really happen
+			return null;
+		}
+
+		return container.findSourceElements(sourcePath);
+	}
+
+	public ISourceContainer getSourceContainer(Object element, boolean refresh, IProgressMonitor monitor) throws CoreException {
+		File location = jdi.getClassesLocation(element);
+
+		if (location == null) {
+			return null;
+		}
+
+		synchronized (containers) {
+			if (!refresh && containers.containsKey(location)) {
+				return containers.get(location);
+			}
+		}
+
+		monitor = getContextMonitor(monitor);
+
+		WorkspaceProjectSourceContainers projectLocator = AdvancedSourceLookupSupport.getWorkspaceJavaProjects(monitor);
+		if (monitor == null && projectLocator == null) {
+			// reschedule to initialize and resolve sources in background
+			AdvancedSourceLookupSupport.schedule((m) -> getSourceContainer(element, refresh, m));
+			return null;
+		}
+
+		if (projectLocator == null) {
+			// we get here when projectLocator initialization has been cancelled by the user
+			return null;
+		}
+
+		//
+		// lookup strategies that provide java project context necessary for debug expression evaluation
+		//
+
+		// workspace project identified by their runtime classes location is the preferred sources container
+		ISourceContainer projectContainer = projectLocator.createProjectContainer(location);
+		if (projectContainer != null) {
+			return cacheContainer(element, location, projectContainer);
+		}
+
+		// dependency of one of workspace projects on the call stack also provides java project context
+		for (File frameLocation : jdi.getStackFramesClassesLocations(element)) {
+			ISourceContainer entryContainer = projectLocator.createClasspathEntryContainer(frameLocation, location);
+			if (entryContainer != null) {
+				return cacheContainer(element, location, entryContainer);
+			}
+		}
+
+		if (monitor == null) {
+			// reschedule to resolve sources in background
+			AdvancedSourceLookupSupport.schedule((m) -> getSourceContainer(element, refresh, m));
+			return null;
+		}
+
+		//
+		// strategies that allow source code lookup but do not provide java project context
+		//
+
+		// checksum-based lookup in various sources (central, nexus, pde target platform, p2 repositories)
+		for (ISourceContainerResolver repository : getSourceContainerResolvers()) {
+			Collection<ISourceContainer> members = repository.resolveSourceContainers(location, monitor);
+			if (members != null && !members.isEmpty()) {
+				return cacheContainer(element, location, CompositeSourceContainer.compose(members));
+			}
+		}
+
+		return null;
+	}
+
+	private ISourceContainer cacheContainer(Object element, File location, ISourceContainer container) {
+		ISourceContainer oldContainer;
+		synchronized (containers) {
+			oldContainer = containers.put(location, container);
+			if (oldContainer != null) {
+				oldContainer.dispose();
+			}
+		}
+		if (oldContainer != null || container != null) {
+			updateDebugElement(element);
+		}
+		return container;
+	}
+
+	protected Collection<ISourceContainerResolver> getSourceContainerResolvers() {
+		List<ISourceContainerResolver> result = new ArrayList<>();
+
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+
+		IConfigurationElement[] elements = registry.getConfigurationElementsFor(AdvancedSourceLookupSupport.ID_sourceContainerResolvers);
+
+		for (IConfigurationElement element : elements) {
+			if ("resolver".equals(element.getName())) { //$NON-NLS-1$
+				try {
+					result.add((ISourceContainerResolver) element.createExecutableExtension("class")); //$NON-NLS-1$
+				}
+				catch (CoreException e) {
+				}
+			}
+		}
+
+		return result;
+	}
+
+	@Override
+	public String getSourceName(Object object) throws CoreException {
+		return null; // default name->source mapping
+	}
+
+	@Override
+	public void dispose() {
+		disposeContainers();
+	}
+
+	@Override
+	public void sourceContainersChanged(ISourceLookupDirector director) {
+		disposeContainers();
+	}
+
+	protected void disposeContainers() {
+		synchronized (containers) {
+			for (ISourceContainer container : containers.values()) {
+				if (container != null) // possible for non-maven jars
+				{
+					container.dispose();
+				}
+			}
+			containers.clear();
+		}
+	}
+
+	private void updateDebugElement(Object element) {
+		director.clearSourceElements(element);
+		if (element instanceof DebugElement) {
+			// this is apparently needed to flush StackFrameSourceDisplayAdapter cache
+			((DebugElement) element).fireChangeEvent(DebugEvent.CONTENT);
+		}
+	}
+
+	public static AdvancedSourceLookupParticipant getSourceLookup(Object element) {
+		ISourceLocator sourceLocator = null;
+		if (element instanceof IDebugElement) {
+			sourceLocator = ((IDebugElement) element).getLaunch().getSourceLocator();
+		}
+
+		AdvancedSourceLookupParticipant sourceLookup = null;
+		if (sourceLocator instanceof ISourceLookupDirector) {
+			for (ISourceLookupParticipant participant : ((ISourceLookupDirector) sourceLocator).getParticipants()) {
+				if (participant instanceof AdvancedSourceLookupParticipant) {
+					sourceLookup = (AdvancedSourceLookupParticipant) participant;
+					break;
+				}
+			}
+		}
+		return sourceLookup;
+	}
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/ISourceContainerResolver.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/ISourceContainerResolver.java
new file mode 100644
index 0000000..28f11a2
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/ISourceContainerResolver.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.launching.sourcelookup.advanced;
+
+import java.io.File;
+import java.util.Collection;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+
+/**
+ * Implementations of this interface identify runtime classes locations and download (or "resolve") corresponding sources from external sources
+ * repositories like Maven or P2 artifact repositories and PDE target platform. Implementations are registered with the advanced source lookup
+ * framework using {@code org.eclipse.jdt.launching.sourceContainerResolvers} extension point.
+ *
+ * @since 3.10
+ * @provisional This is part of work in progress and can be changed, moved or removed without notice
+ */
+public interface ISourceContainerResolver {
+
+	/**
+	 * Creates and returns a collection of source containers that correspond to the given filesystem classes location. Returns {@code null} or an
+	 * empty collection if requested sources cannot be located.
+	 */
+	public Collection<ISourceContainer> resolveSourceContainers(File classesLocation, IProgressMonitor monitor) throws CoreException;
+
+}
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/IWorkspaceProjectDescriber.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/IWorkspaceProjectDescriber.java
new file mode 100644
index 0000000..7d8b2c0
--- /dev/null
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/sourcelookup/advanced/IWorkspaceProjectDescriber.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *      Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.launching.sourcelookup.advanced;
+
+import java.io.File;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+
+/**
+ * Implementations of this interface describe workspace projects for the purpose of source lookup. Implementations are registered with the advanced
+ * source lookup framework using {@code org.eclipse.jdt.launching.workspaceProjectDescribers} extension point.
+ *
+ * Workspace project runtime classes location are used to identify projects when performing source code lookup. Depending on project type and
+ * application classloading mechanism used by the runtime, classes location can be project output folders, one of project classpath entries (for PDE
+ * Binary Plug-In projects, for example) or some other runtime-specific location, like OSGi bundle installation location.
+ *
+ * The same workspace project can have different classes location if it is used with different runtime technologies. For example, PDE Plug-In project
+ * classes will have bundle installation location when used by Equinox framework and project output folder when used by standard java application.
+ * Note that different runtime technologies can coexist within the same running JVM, like it is the case with Tycho build, where Equinox, Maven and
+ * standard Java APIs are used side-by-side. For this reason multiple project describers can provide information about the same project and all
+ * projects descriptions will be considered when performing source lookup.
+ *
+ * @since 3.10
+ * @provisional This is part of work in progress and can be changed, moved or removed without notice
+ */
+public interface IWorkspaceProjectDescriber {
+
+	public static interface IJavaProjectSourceDescription {
+		/**
+		 * Adds filesystem classes directories or jar files as reported by the runtime for project classes.
+		 *
+		 * Some common examples:
+		 * <ul>
+		 * <li>for standard java projects this is project output locations
+		 * <li>for M2E Binary Maven projects, this is one of project claspath entries
+		 * <li>for PDE Plug-In projects used by Equinox, this is project bundle installation location
+		 * <li>for PDE Plug-In projects used plain java, this is still project output locations
+		 * </ul>
+		 *
+		 */
+		public void addLocation(File location);
+
+		/**
+		 * Adds factory of source container(s) for the project itself, typically:
+		 * <ul>
+		 * <li>JavaProjectSourceContainer for normal projects with sources folders
+		 * <li>PackageFragmentRootSourceContainer for PDE and M2E binary projects
+		 * </ul>
+		 *
+		 * In some cases one project will have multiple associated source container. For example, Binary Maven project that represents an "uber" jar
+		 * will have a source container factory for each jar included in the uber jar.
+		 */
+		public void addSourceContainerFactory(Supplier<ISourceContainer> factory);
+
+		/**
+		 * Adds runtime classes location of project dependencies and their corresponding package fragment roots, typically
+		 * <ul>
+		 * <li>for standard java application, this is dependency jar or classes directory
+		 * <li>for equinox, this is dependency bundle location
+		 * </ul>
+		 */
+		public void addDependencies(Map<File, IPackageFragmentRoot> dependencies);
+	}
+
+	/**
+	 * Populate the given description with the given project's description.
+	 */
+	public void describeProject(IJavaProject project, IJavaProjectSourceDescription description) throws CoreException;
+
+}
diff --git a/org.eclipse.jdt.launching/lib/javaagent-shaded.jar b/org.eclipse.jdt.launching/lib/javaagent-shaded.jar
new file mode 100644
index 0000000..718a657
--- /dev/null
+++ b/org.eclipse.jdt.launching/lib/javaagent-shaded.jar
Binary files differ
diff --git a/org.eclipse.jdt.launching/plugin.properties b/org.eclipse.jdt.launching/plugin.properties
index ce69893..b218c27 100644
--- a/org.eclipse.jdt.launching/plugin.properties
+++ b/org.eclipse.jdt.launching/plugin.properties
@@ -11,10 +11,14 @@
 
 localJavaApplication = Java Application
 eclipseJDTLauncher.name=Eclipse JDT Launcher
+localAdvancedJavaApplication.name=Eclipse JDT Advanced
 localJavaApplicationDelegate.description=The Eclipse JDT Java Application Launcher supports running and debugging local Java applications.
+localAdvancedJavaApplicationDelegate.description=The Eclipse JDT Advanced Java Application Launcher supports running and debugging local Java applications.
 pluginName = Java Development Tools Launching Support
 remoteJavaApplication = Remote Java Application
+remoteAdvancedJavaApplication.name = Advanced Remote Java Application
 remoteJavaApplicationDelegate.description=The Eclipse JDT Java Remote Launcher supports attaching to and debugging remote Java applications.
+remoteAdvancedJavaApplicationDelegate.description=The Eclipse JDT Java Remote Launcher with advanced source code lookup.
 vmConnectors = VM Connectors
 vmInstallTypes = VM Install Types
 vmInstalls = VM Installs
@@ -24,6 +28,8 @@
 javaSourceLocatorName = Basic Java Source Locator
 executionEnvironments = Execution Environments
 libraryLocationResolvers = Library Location Resolvers
+projectSourceDescribers = Project Source Describers
+sourceContainerResolvers = Source Container Resolvers
 
 providerName=Eclipse.org
 
@@ -33,6 +39,7 @@
 javaAppletDelegate.description=The Eclipse JDT Java Applet Launcher supports running and debugging Java applets.
 
 javaSourceLookupDirector.name= Java Source Locator
+javaAdvancedSourceLookupDirector.name= Java Advanced Source Locator
 
 launchingTrace.name = JDT Launching
 
@@ -65,3 +72,4 @@
 
 ee.home.description = Returns the absolute file system path of the JRE home directory corresponding to the specified execution environment. An execution environment identifier must be provided as an argument.
 project.classpath.description = Returns the resolved class path of a project. A project name can be provided as an argument. If no argument is provided, the target project is the project of the selected resource.
+sourcelookup.javaagent.description = Returns absolute filesystem path of source lookup java agent.
\ No newline at end of file
diff --git a/org.eclipse.jdt.launching/plugin.xml b/org.eclipse.jdt.launching/plugin.xml
index e0d5899..0789257 100644
--- a/org.eclipse.jdt.launching/plugin.xml
+++ b/org.eclipse.jdt.launching/plugin.xml
@@ -23,6 +23,8 @@
    <extension-point id="executionEnvironments" name="%executionEnvironments" schema="schema/executionEnvironments.exsd"/>
    <extension-point id="vmInstalls" name="%vmInstalls" schema="schema/vmInstalls.exsd"/>
    <extension-point id="libraryLocationResolvers" name="%libraryLocationResolvers" schema="schema/libraryLocationResolvers.exsd"/>
+   <extension-point id="workspaceProjectDescribers" name="%projectSourceDescribers" schema="schema/workspaceProjectDescribers.exsd"/>
+   <extension-point id="sourceContainerResolvers" name="%sourceContainerResolvers" schema="schema/sourceContainerResolvers.exsd"/>
 
 <!-- Extensions -->
    <extension
@@ -43,7 +45,8 @@
    <extension
          point="org.eclipse.debug.core.launchConfigurationTypes">
       <launchConfigurationType
-            delegate="org.eclipse.jdt.launching.JavaLaunchDelegate"
+            allowPrototypes="true"
+            delegate="org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedJavaLaunchDelegate"
             delegateDescription="%localJavaApplicationDelegate.description"
             delegateName="%eclipseJDTLauncher.name"
             id="org.eclipse.jdt.launching.localJavaApplication"
@@ -54,7 +57,7 @@
             sourcePathComputerId="org.eclipse.jdt.launching.sourceLookup.javaSourcePathComputer">
       </launchConfigurationType>
       <launchConfigurationType
-            delegate="org.eclipse.jdt.internal.launching.JavaRemoteApplicationLaunchConfigurationDelegate"
+            delegate="org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedRemoteJavaLaunchDelegate"
             delegateDescription="%remoteJavaApplicationDelegate.description"
             delegateName="%eclipseJDTLauncher.name"
             id="org.eclipse.jdt.launching.remoteJavaApplication"
@@ -201,6 +204,11 @@
    			class="org.eclipse.jdt.internal.launching.JavaSourceLookupDirector"
    			name="%javaSourceLookupDirector.name">
    		</sourceLocator>
+   		<sourceLocator
+   			id="org.eclipse.jdt.launching.sourceLocator.JavaAdvancedSourceLookupDirector"
+   			class="org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupDirector"
+   			name="%javaAdvancedSourceLookupDirector.name">
+   		</sourceLocator>
    </extension>
    <extension
          point="org.eclipse.core.runtime.preferences">
@@ -229,6 +237,12 @@
             namespace="org.eclipse.jdt.launching"
             properties="hasMain, extendsClass, extendsInterface, hasMethod, isContainer, hasProjectNature, buildpathReference, hasMethodWithAnnotation, hasTypeWithAnnotation, isPackageFragment, isPackageFragmentRoot"
             type="org.eclipse.core.runtime.IAdaptable"/>            
+      <propertyTester
+            class="org.eclipse.jdt.internal.launching.sourcelookup.advanced.JDIStratumPropertyTester"
+            id="org.eclipse.jdt.internal.launching.sourcelookup.advanced.jdtStratumTest"
+            namespace="org.eclipse.jdt.launching"
+            properties="jdtstratum"
+            type="org.eclipse.debug.core.model.DebugElement"/>
    </extension>
    <extension
          id="jreContainerMarker"
@@ -335,6 +349,12 @@
                name="project_classpath"
                resolver="org.eclipse.jdt.internal.launching.ProjectClasspathVariableResolver">
          </variable>
+         <variable
+               description="%sourcelookup.javaagent.description"
+               name="sourcelookup_javaagent"
+               resolver="org.eclipse.jdt.internal.launching.sourcelookup.advanced.JavaagentVariableResolver"
+               supportsArgument="false">
+         </variable>
       </extension>
       <extension
             point="org.eclipse.jdt.launching.libraryLocationResolvers">
diff --git a/org.eclipse.jdt.launching/pom.xml b/org.eclipse.jdt.launching/pom.xml
index 0c1c5f9..3dad1bb 100644
--- a/org.eclipse.jdt.launching/pom.xml
+++ b/org.eclipse.jdt.launching/pom.xml
@@ -14,11 +14,11 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.3-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.launching</artifactId>
-  <version>3.9.52-SNAPSHOT</version>
+  <version>3.10.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
   
   <build>
diff --git a/org.eclipse.jdt.launching/schema/sourceContainerResolvers.exsd b/org.eclipse.jdt.launching/schema/sourceContainerResolvers.exsd
new file mode 100644
index 0000000..2d26f58
--- /dev/null
+++ b/org.eclipse.jdt.launching/schema/sourceContainerResolvers.exsd
@@ -0,0 +1,90 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.jdt.launching" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.jdt.launching" id="sourceContainerResolvers" name="Source Container Resolvers"/>
+      </appInfo>
+      <documentation>
+         This extension point allows clients to identify and download sources jar artifacts from external artifact repositories.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="resolver" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="resolver">
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.jdt.launching.sourcelookup.advanced.ISourceContainerResolver"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         3.9
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2011-2016 Igor Fedorenko
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+     Igor Fedorenko - initial API and implementation
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/org.eclipse.jdt.launching/schema/workspaceProjectDescribers.exsd b/org.eclipse.jdt.launching/schema/workspaceProjectDescribers.exsd
new file mode 100644
index 0000000..88abadb
--- /dev/null
+++ b/org.eclipse.jdt.launching/schema/workspaceProjectDescribers.exsd
@@ -0,0 +1,101 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.jdt.launching" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.jdt.launching" id="workspaceProjectDescribers" name="Workspace Project Describers"/>
+      </appInfo>
+      <documentation>
+         This extension point allows clients to support advanced source lookup functionality for workspace Java projects with non-default layout, e.g. &quot;binary-only&quot; projects, projects with custom classpath container, like PDE Plugin-In or Maven projects, and so on.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="describer" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="describer">
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.jdt.launching.sourcelookup.advanced.IWorkspaceProjectDescriber"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         3.9
+      </documentation>
+   </annotation>
+
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         Implementation is provided for the standard Eclipse JDT java project type.
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2011-2016 Igor Fedorenko
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+     Igor Fedorenko - initial API and implementation
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/pom.xml b/pom.xml
index 49631e4..1fe85b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,13 +15,13 @@
   <parent>
     <groupId>org.eclipse</groupId>
     <artifactId>eclipse-platform-parent</artifactId>
-    <version>4.7.3-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
     <relativePath>../eclipse-platform-parent</relativePath>
   </parent>
 
   <groupId>eclipse.jdt.debug</groupId>
   <artifactId>eclipse.jdt.debug</artifactId>
-  <version>4.7.3-SNAPSHOT</version>
+  <version>4.8.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <properties>