Merge R4_7_maintenance for Java9 


Change-Id: I48fb21fe5f390df028256690048dfb7335770219
diff --git a/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF
index bea7112..d7b71c1 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.0.qualifier
+Bundle-Version: 3.11.100.qualifier
 Bundle-ClassPath: javadebugtests.jar
 Bundle-Activator: org.eclipse.jdt.debug.testplugin.JavaTestPlugin
 Bundle-Vendor: %providerName
diff --git a/org.eclipse.jdt.debug.tests/pom.xml b/org.eclipse.jdt.debug.tests/pom.xml
index 216d2e9..7ad17c8 100644
--- a/org.eclipse.jdt.debug.tests/pom.xml
+++ b/org.eclipse.jdt.debug.tests/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.1-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.debug.tests</artifactId>
-  <version>3.11.0-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/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/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..0b17dd8 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
@@ -19,6 +19,9 @@
 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 +47,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 +472,35 @@
 		}
 	}
 
+	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();
+		}
+	}
 }
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..1683524 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
@@ -197,7 +197,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" };
+			"StepResult2", "StepResult3", "StepUncaught", "TriggerPoint_01", "BulkThreadCreationTest" };
 
 	final String[] LAUNCH_CONFIG_NAMES_1_8 = {"LargeSourceFile"};
 
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..01b9816 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
@@ -58,6 +58,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 +118,6 @@
 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.DetailPaneManagerTests;
 import org.eclipse.jdt.debug.tests.ui.OpenFromClipboardTests;
 import org.eclipse.jdt.debug.tests.ui.ViewManagementTests;
@@ -279,6 +279,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 +322,8 @@
 		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));
 
 	// 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/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.ui/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF
index a498154..c95f11d 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.50.qualifier
+Bundle-Version: 3.9.0.qualifier
 Bundle-Activator: org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/org.eclipse.jdt.debug.ui/forceQualifierUpdate.txt b/org.eclipse.jdt.debug.ui/forceQualifierUpdate.txt
new file mode 100644
index 0000000..df66e6c
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/forceQualifierUpdate.txt
@@ -0,0 +1,2 @@
+# To force a version qualifier update, add the bug here
+Bug 522092 - Comparator errors from I20170909-0920
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug.ui/pom.xml b/org.eclipse.jdt.debug.ui/pom.xml
index fb3f42e..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.1-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.debug.ui</artifactId>
-  <version>3.8.50-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/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug/META-INF/MANIFEST.MF
index 21efd30..307a3f7 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
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/breakpoints/JavaBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java
index cad7552..ba6a3fe 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
@@ -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;
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/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/JDIThread.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java
index b8de172..f2572fd 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, 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
@@ -2585,7 +2585,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 +2714,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
@@ -3734,4 +3732,11 @@
 		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());
+	}
+
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.debug/pom.xml b/org.eclipse.jdt.debug/pom.xml
index 0f59d74..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.1-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.macosx/pom.xml b/org.eclipse.jdt.launching.macosx/pom.xml
index 0cd5fc3..4fa9bcf 100644
--- a/org.eclipse.jdt.launching.macosx/pom.xml
+++ b/org.eclipse.jdt.launching.macosx/pom.xml
@@ -14,7 +14,7 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.1-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.launching.macosx</artifactId>
diff --git a/org.eclipse.jdt.launching.ui.macosx/pom.xml b/org.eclipse.jdt.launching.ui.macosx/pom.xml
index 89a135e..a34fd6c 100644
--- a/org.eclipse.jdt.launching.ui.macosx/pom.xml
+++ b/org.eclipse.jdt.launching.ui.macosx/pom.xml
@@ -14,7 +14,7 @@
   <parent>
     <artifactId>eclipse.jdt.debug</artifactId>
     <groupId>eclipse.jdt.debug</groupId>
-    <version>4.7.1-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.launching.ui.macosx</artifactId>
diff --git a/org.eclipse.jdt.launching/META-INF/MANIFEST.MF b/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
index 74827e8..fc0027d 100644
--- a/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.launching/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.launching; singleton:=true
-Bundle-Version: 3.9.50.qualifier
+Bundle-Version: 3.10.0.qualifier
 Bundle-Activator: org.eclipse.jdt.internal.launching.LaunchingPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/org.eclipse.jdt.launching/pom.xml b/org.eclipse.jdt.launching/pom.xml
index bbc967c..3dad1bb 100644
--- a/org.eclipse.jdt.launching/pom.xml
+++ b/org.eclipse.jdt.launching/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.1-SNAPSHOT</version>
+    <version>4.8.0-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.launching</artifactId>
-  <version>3.9.50-SNAPSHOT</version>
+  <version>3.10.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
   
   <build>
diff --git a/pom.xml b/pom.xml
index 86f2743..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.1-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.1-SNAPSHOT</version>
+  <version>4.8.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <properties>