Merge remote-tracking branch 'origin/master' into BETA_JAVA_12

Change-Id: Ibf50d6bdc251efb9404f80eabfb1bdac6a289452
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/DebugSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/DebugSuite.java
index cd08506..a6f413b 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/DebugSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/DebugSuite.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2015 IBM Corporation and others.
+ *  Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  *  This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License 2.0
@@ -10,6 +10,7 @@
  *
  *  Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Paul Pazderski  - Bug 544133: signal end of test runner in any case
  *******************************************************************************/
 package org.eclipse.jdt.debug.tests;
 
@@ -31,7 +32,6 @@
 	 */
 	protected boolean fTesting = true;
 
-
 	/**
 	 * Construct the test suite.
 	 */
@@ -52,18 +52,21 @@
 			Runnable r = new Runnable() {
 				@Override
 				public void run() {
-					for (Enumeration<Test> e= tests(); e.hasMoreElements(); ) {
-				  		if (result.shouldStop() ) {
-							break;
+					try {
+						for (Enumeration<Test> e= tests(); e.hasMoreElements(); ) {
+							if (result.shouldStop()) {
+								break;
+							}
+							Test test= e.nextElement();
+							runTest(test, result);
 						}
-						Test test= e.nextElement();
-						runTest(test, result);
+					} finally {
+						fTesting = false;
+						display.wake();
 					}
-					fTesting = false;
-					display.wake();
 				}
 			};
-			thread = new Thread(r);
+			thread = new Thread(r, "Test Runner");
 			thread.start();
 		} catch (Exception e) {
 			e.printStackTrace();
@@ -79,6 +82,4 @@
 			}
 		}
 	}
-
 }
-
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ManualSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ManualSuite.java
index a74b86e..669014d 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ManualSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ManualSuite.java
@@ -13,25 +13,16 @@
  *******************************************************************************/
 package org.eclipse.jdt.debug.tests;
 
-import java.util.Enumeration;
-
 import org.eclipse.jdt.debug.tests.core.RemoteJavaApplicationTests;
-import org.eclipse.swt.widgets.Display;
 
 import junit.framework.Test;
-import junit.framework.TestResult;
 import junit.framework.TestSuite;
 
 /**
  * Tests that are to be run manually by the debug team, in addition to
  * automated tests.
  */
-public class ManualSuite extends TestSuite {
-
-	/**
-	 * Flag that indicates test are in progress
-	 */
-	protected boolean fTesting = true;
+public class ManualSuite extends DebugSuite {
 
 	/**
 	 * Returns the suite.  This is required to
@@ -55,48 +46,5 @@
 		addTest(new TestSuite(RemoteJavaApplicationTests.class));
 
 	}
-
-	/**
-	 * Runs the tests and collects their result in a TestResult.
-	 * The debug tests cannot be run in the UI thread or the event
-	 * waiter blocks the UI when a resource changes.
-	 * @see junit.framework.TestSuite#run(junit.framework.TestResult)
-	 */
-	@Override
-	public void run(final TestResult result) {
-		final Display display = Display.getCurrent();
-		Thread thread = null;
-		try {
-			Runnable r = new Runnable() {
-				@Override
-				public void run() {
-					for (Enumeration<Test> e= tests(); e.hasMoreElements(); ) {
-				  		if (result.shouldStop() ) {
-							break;
-						}
-						Test test= e.nextElement();
-						runTest(test, result);
-					}
-					fTesting = false;
-					display.wake();
-				}
-			};
-			thread = new Thread(r);
-			thread.start();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-
-		while (fTesting) {
-			try {
-				if (!display.readAndDispatch()) {
-					display.sleep();
-				}
-			} catch (Throwable e) {
-				e.printStackTrace();
-			}
-		}
-	}
-
 }
 
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 afd3f68..9528825 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
@@ -21,16 +21,20 @@
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IBreakpoint;
 import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
 import org.eclipse.debug.ui.console.IConsole;
 import org.eclipse.debug.ui.console.IConsoleLineTrackerExtension;
 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint;
+import org.eclipse.jdt.debug.core.JDIDebugModel;
 import org.eclipse.jdt.debug.testplugin.ConsoleLineTracker;
 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.jdt.internal.debug.ui.console.JavaExceptionHyperLink;
 import org.eclipse.jdt.internal.debug.ui.console.JavaStackTraceHyperlink;
+import org.eclipse.jdt.internal.debug.ui.propertypages.JavaBreakpointPage;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IRegion;
@@ -182,6 +186,77 @@
 	    }
 	}
 
+	public void testJavaExceptionHyperLink() throws Exception {
+		ConsoleLineTracker.setDelegate(this);
+		fTarget = null;
+		IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore();
+		boolean suspendOnException = jdiUIPreferences.getBoolean(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS);
+		jdiUIPreferences.setValue(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, false);
+		try {
+			fTarget = launchAndTerminate("ThrowsNPE");
+
+			synchronized (fLock) {
+				if (!fStopped) {
+					fLock.wait(30000);
+				}
+			}
+			assertTrue("Never received 'start' notification", fStarted);
+			assertTrue("Never received 'stopped' notification", fStopped);
+			assertTrue("Console should be an IOCosnole", fConsole instanceof IOConsole);
+			IOConsole console = (IOConsole) fConsole;
+			IHyperlink[] hyperlinks = console.getHyperlinks();
+
+			// should be 1 exception hyperlink
+			int total = 0;
+			for (int i = 0; i < hyperlinks.length; i++) {
+				IHyperlink hyperlink = hyperlinks[i];
+				if (hyperlink instanceof JavaExceptionHyperLink) {
+					total++;
+					// should be followed by a stack trace hyperlink
+					assertTrue("Stack trace hyperlink missing", hyperlinks[i + 1] instanceof JavaStackTraceHyperlink);
+				}
+			}
+			assertEquals("Wrong number of exception hyperlinks", 1, total);
+			IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(JDIDebugModel.getPluginIdentifier());
+			IJavaExceptionBreakpoint foundBreakpoint = null;
+			for (int i = 0; i < breakpoints.length; i++) {
+				IBreakpoint breakpoint = breakpoints[i];
+				if (breakpoint instanceof IJavaExceptionBreakpoint) {
+					IJavaExceptionBreakpoint exceptionBreakpoint = (IJavaExceptionBreakpoint) breakpoint;
+					if ("java.lang.NullPointerException".equals(exceptionBreakpoint.getTypeName())) {
+						foundBreakpoint = exceptionBreakpoint;
+						break;
+					}
+				}
+			}
+			assertTrue("NPE breakpoint should not exist yet", foundBreakpoint == null);
+			IJavaExceptionBreakpoint ex = createExceptionBreakpoint("java.lang.NullPointerException", true, false);
+			ex.setEnabled(false);
+			JavaExceptionHyperLink exLink = (JavaExceptionHyperLink) hyperlinks[0];
+			exLink.linkActivated();
+			breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(JDIDebugModel.getPluginIdentifier());
+			foundBreakpoint = null;
+			for (int i = 0; i < breakpoints.length; i++) {
+				IBreakpoint breakpoint = breakpoints[i];
+				if (breakpoint instanceof IJavaExceptionBreakpoint) {
+					IJavaExceptionBreakpoint exceptionBreakpoint = (IJavaExceptionBreakpoint) breakpoint;
+					if ("java.lang.NullPointerException".equals(exceptionBreakpoint.getTypeName())) {
+						foundBreakpoint = exceptionBreakpoint;
+						break;
+					}
+				}
+			}
+			assertTrue("NPE breakpoint not found", foundBreakpoint != null);
+			assertTrue("NPE breakpoint not enabled", foundBreakpoint.isEnabled());
+			assertTrue("NPE breakpoint cancel enablement value not false", foundBreakpoint.getMarker().getAttribute(JavaBreakpointPage.ATTR_ENABLED_SETTING_ON_CANCEL, "").equals("false"));
+		} finally {
+			ConsoleLineTracker.setDelegate(null);
+			jdiUIPreferences.setValue(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, suspendOnException);
+			terminateAndRemove(fTarget);
+		}
+
+	}
+
 	/**
 	 * @see org.eclipse.debug.ui.console.IConsoleLineTracker#dispose()
 	 */
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/console/JavaStackTraceConsoleFactory.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/console/JavaStackTraceConsoleFactory.java
index 3a8e3d6..15aee2a 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/console/JavaStackTraceConsoleFactory.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/console/JavaStackTraceConsoleFactory.java
@@ -68,10 +68,13 @@
 	public void openConsole(String initialText) {
 		if (fConsole == null) {
 			fConsole = new JavaStackTraceConsole();
-			fConsole.initializeDocument();
+			if (initialText != null) {
+				fConsole.getDocument().set(initialText);
+			} else {
+				fConsole.initializeDocument();
+			}
 			fConsoleManager.addConsoles(new IConsole[] { fConsole });
-		}
-		if (initialText != null) {
+		} else if (initialText != null) {
 			fConsole.getDocument().set(initialText);
 		}
 		fConsoleManager.showConsoleView(fConsole);
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 523e16e..ed5690f 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
@@ -41,7 +41,7 @@
 		store.setDefault(IJDIPreferencesConstants.PREF_SHOW_QUALIFIED_NAMES, false);
 
 		// JavaStepFilterPreferencePage
-		store.setDefault(IJDIPreferencesConstants.PREF_ACTIVE_FILTERS_LIST, "java.lang.ClassLoader"); //$NON-NLS-1$
+		store.setDefault(IJDIPreferencesConstants.PREF_ACTIVE_FILTERS_LIST, "java.lang.ClassLoader,org.eclipse.jdt.launching.internal.*"); //$NON-NLS-1$
 		store.setDefault(IJDIPreferencesConstants.PREF_INACTIVE_FILTERS_LIST, "com.ibm.*,com.sun.*,java.*,javax.*,jrockit.*,org.omg.*,sun.*,sunw.*"); //$NON-NLS-1$
 		store.setDefault(IJDIPreferencesConstants.PREF_STEP_THRU_FILTERS, true);
 
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDetailFormattersManager.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDetailFormattersManager.java
index 281fa06..9092730 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDetailFormattersManager.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JavaDetailFormattersManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -33,6 +33,7 @@
 import org.eclipse.debug.ui.IValueDetailListener;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.debug.core.IEvaluationRunnable;
 import org.eclipse.jdt.debug.core.IJavaArray;
@@ -379,11 +380,16 @@
 			return fCacheMap.get(key);
 		}
 		String snippet = null;
+
 		if (type instanceof IJavaClassType) {
 			snippet = getDetailFormatter((IJavaClassType) type);
-		} else if (type instanceof IJavaArrayType) {
-			snippet = getArraySnippet((IJavaArray) javaObject);
 		}
+		if (type instanceof IJavaArrayType) {
+			if (JavaCore.compareJavaVersions(debugTarget.getVersion(), JavaCore.VERSION_9) < 0) {
+				snippet = getArraySnippet((IJavaArray) javaObject);
+			}
+		}
+
 		if (snippet != null) {
 			IJavaProject project = getJavaProject(javaObject, thread);
 			if (project != null) {
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/console/JavaExceptionHyperLink.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/console/JavaExceptionHyperLink.java
index 1c67f33..77f6cd6 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/console/JavaExceptionHyperLink.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/console/JavaExceptionHyperLink.java
@@ -68,6 +68,9 @@
 				if (breakpoint instanceof IJavaExceptionBreakpoint) {
 					IJavaExceptionBreakpoint exceptionBreakpoint = (IJavaExceptionBreakpoint) breakpoint;
 					if (fExceptionName.equals(exceptionBreakpoint.getTypeName())) {
+						// reset enabled setting to true but save original value to reset if user cancels dialog
+						exceptionBreakpoint.getMarker().setAttribute(JavaBreakpointPage.ATTR_ENABLED_SETTING_ON_CANCEL, Boolean.toString(exceptionBreakpoint.isEnabled()));
+						exceptionBreakpoint.setEnabled(true);
 						showProperties(exceptionBreakpoint);
 						return;
 					}
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 0ab955f..ad1c819 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, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -991,7 +991,14 @@
 						IVMInstallType type = vmTypes[j];
 						IStatus status = type.validateInstallLocation(file);
 						if (status.isOK()) {
-							found.add(file);
+							String filePath = file.getPath();
+							int index = filePath.lastIndexOf(File.separatorChar);
+							File newFile = file;
+							// remove bin folder from install location as java executables are found only under bin for Java 9 and above
+							if (index > 0 && filePath.substring(index + 1).equals("bin")) { //$NON-NLS-1$
+								newFile = new File(filePath.substring(0, index));
+							}
+							found.add(newFile);
 							types.add(type);
 							validLocation = true;
 							break;
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java
index 7516044..cfbaa40 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java
@@ -81,6 +81,11 @@
 	public static final String ATTR_DELETE_ON_CANCEL = JDIDebugUIPlugin.getUniqueIdentifier() + ".ATTR_DELETE_ON_CANCEL";  //$NON-NLS-1$
 
 	/**
+	 * Attribute used to indicate resetting the enable attribute if cancel is pressed.
+	 */
+	public static final String ATTR_ENABLED_SETTING_ON_CANCEL = JDIDebugUIPlugin.getUniqueIdentifier() + ".ATTR_ENABLED_SETTING_ON_CANCEL"; //$NON-NLS-1$
+
+	/**
 	 * Constant for the empty string
 	 */
 	protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
@@ -102,6 +107,7 @@
 					breakpoint.getMarker().setAttribute(ATTR_DELETE_ON_CANCEL, (String)null);
 					breakpoint.setRegistered(true);
 				}
+				breakpoint.getMarker().setAttribute(ATTR_ENABLED_SETTING_ON_CANCEL, (String) null);
 				doStore();
 			}
 		};
@@ -415,6 +421,12 @@
 	@Override
 	public boolean performCancel() {
 		try {
+			String enableSetting = getBreakpoint().getMarker().getAttribute(ATTR_ENABLED_SETTING_ON_CANCEL, null);
+			if (enableSetting != null) {
+				// if this is an old breakpoint we must reset enablement setting
+				boolean enabled = Boolean.parseBoolean(enableSetting);
+				getBreakpoint().setEnabled(enabled);
+			}
 			if (getBreakpoint().getMarker().getAttribute(ATTR_DELETE_ON_CANCEL) != null) {
 			    // if this breakpoint is being created, delete on cancel
 				getBreakpoint().delete();
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties
index c982cb4..904b158 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties
@@ -59,7 +59,7 @@
 JavaLineBreakpointPage_18=Line Breakpoint
 JavaLineBreakpointPage_19=Watchpoint
 JavaLineBreakpointPage_20=Method Breakpoint
-JavaVariableDetailsPane_choosePreviousExpression=<Choose a previously entered expression for debugging>
+JavaVariableDetailsPane_choosePreviousExpression=<Choose a previously entered expression>
 JavaVariableDetailsPane_description=Java Variable Detail Pane Viewer
 JavaVariableDetailsPane_historySeparator=Global history
 JavaVariableDetailsPane_name=Java Variable Detail Pane Viewer
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPane.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPane.java
index 41399b1..01267e3 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPane.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariablesDetailPane.java
@@ -13,11 +13,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.debug.ui.variables;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Stack;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.regex.Pattern;
 
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IValue;
 import org.eclipse.debug.internal.ui.SWTFactory;
 import org.eclipse.debug.internal.ui.views.variables.details.DefaultDetailPane;
 import org.eclipse.jdt.debug.core.IJavaVariable;
@@ -26,15 +29,18 @@
 import org.eclipse.jdt.internal.debug.ui.propertypages.PropertyPageMessages;
 import org.eclipse.jface.dialogs.DialogSettings;
 import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.fieldassist.ControlDecoration;
+import org.eclipse.jface.fieldassist.FieldDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
 import org.eclipse.jface.text.source.SourceViewer;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.FocusEvent;
 import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
@@ -57,15 +63,16 @@
 	private FocusListener focusListener;
 	private Combo fExpressionHistory;
 	private IDialogSettings fExpressionHistoryDialogSettings;
-	private Map<IJavaVariable, Stack<String>> fLocalExpressionHistory;
-	private int fSeparatorIndex;
-	private static final int MAX_HISTORY_SIZE = 10;
+	private static final int MAX_HISTORY_SIZE = 20;
 	private static final String DS_SECTION_EXPRESSION_HISTORY = "expressionHistory"; //$NON-NLS-1$
 	private static final String DS_KEY_HISTORY_ENTRY_COUNT = "expressionHistoryEntryCount"; //$NON-NLS-1$
 	private static final String DS_KEY_HISTORY_ENTRY_PREFIX = "expressionHistoryEntry_"; //$NON-NLS-1$
 	private static final Pattern NEWLINE_PATTERN = Pattern.compile("\r\n|\r|\n"); //$NON-NLS-1$ ;
 
 	private IJavaVariable fVariable;
+	private IValue fValue;
+	private boolean textModified = false;
+
 	public JavaVariablesDetailPane() {
 		fExpressionHistoryDialogSettings = DialogSettings.getOrCreateSection(JDIDebugUIPlugin.getDefault().getDialogSettings(), DS_SECTION_EXPRESSION_HISTORY);
 	}
@@ -78,14 +85,14 @@
 			return c;
 		}
 		if (fExpressionHistoryDialogSettings != null) {
-			fLocalExpressionHistory = new HashMap<>();
 			fExpressionHistory = SWTFactory.createCombo(parent, SWT.DROP_DOWN | SWT.READ_ONLY, 1, null);
 			fExpressionHistory.addSelectionListener(new SelectionAdapter() {
 				@Override
 				public void widgetSelected(SelectionEvent e) {
 					int historyIndex = fExpressionHistory.getSelectionIndex() - 1;
-					if (historyIndex >= 0 && historyIndex != fSeparatorIndex && getSourceViewer() != null) {
+					if (historyIndex >= 0 && getSourceViewer() != null) {
 						getSourceViewer().getDocument().set(getExpressionHistory()[historyIndex]);
+						textModified = true;
 					}
 				}
 			});
@@ -96,20 +103,37 @@
 		}
 		Control newControl = super.createControl(parent);
 		SourceViewer viewer = getSourceViewer();
-		focusListener = new FocusListener() {
+		// Light bulb for content assist hint
+		ControlDecoration decoration = new ControlDecoration(viewer.getControl(), SWT.TOP | SWT.LEFT);
+		decoration.setShowOnlyOnFocus(true);
+		FieldDecoration dec = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL);
+		decoration.setImage(dec.getImage());
+		decoration.setDescriptionText(dec.getDescription());
 
+		focusListener = new FocusListener() {
 			@Override
 			public void focusLost(FocusEvent e) {
 				updateExpressionHistories();
-				initializeExpressionHistoryDropDown();
+				fValue = null;
 			}
-
 			@Override
 			public void focusGained(FocusEvent e) {
-
+				fValue = null;
+				try {
+					if (fVariable != null) {
+						fValue = fVariable.getValue();
+					}
+				} catch (DebugException ex) {
+				}
 			}
 		};
 		viewer.getTextWidget().addFocusListener(focusListener);
+		viewer.getTextWidget().addModifyListener(new ModifyListener() {
+			@Override
+			public void modifyText(ModifyEvent e) {
+				textModified = true;
+			}
+		});
 		return newControl;
 	}
 
@@ -143,27 +167,8 @@
 	 * @return an array of strings containing the history of Expressions
 	 */
 	private String[] getExpressionHistory() {
-		fSeparatorIndex = -1;
-
 		// Get global history
-		String[] globalItems = readExpressionHistory(fExpressionHistoryDialogSettings);
-
-		// Get local history
-		Stack<String> localHistory = fLocalExpressionHistory.get(fVariable);
-		if (localHistory == null) {
-			return globalItems;
-		}
-
-		// Create combined history
-		int localHistorySize = Math.min(localHistory.size(), MAX_HISTORY_SIZE);
-		String[] historyItems = new String[localHistorySize + globalItems.length + 1];
-		for (int i = 0; i < localHistorySize; i++) {
-			historyItems[i] = localHistory.get(localHistory.size() - i - 1);
-		}
-		fSeparatorIndex = localHistorySize;
-		historyItems[localHistorySize] = getSeparatorLabel();
-		System.arraycopy(globalItems, 0, historyItems, localHistorySize + 1, globalItems.length);
-		return historyItems;
+		return readExpressionHistory(fExpressionHistoryDialogSettings);
 	}
 
 	/**
@@ -171,20 +176,18 @@
 	 */
 	private void updateExpressionHistories() {
 		String newItem = getSourceViewer().getDocument().get();
-		if (newItem.length() == 0) {
+		if (newItem.length() == 0 || fValue == null) {
 			return;
 		}
 
-		// Update local history
-		Stack<String> localHistory = fLocalExpressionHistory.get(fVariable);
-		if (localHistory == null) {
-			localHistory = new Stack<>();
-			fLocalExpressionHistory.put(fVariable, localHistory);
+		String oldValue = fValue.toString();
+		if (oldValue.charAt(0) == '"' && oldValue.charAt(oldValue.length() - 1) == '"') {
+			oldValue = oldValue.substring(1, oldValue.length() - 1);
 		}
-
-		localHistory.remove(newItem);
-		localHistory.push(newItem);
-
+		if (!textModified || newItem.equals(oldValue)) {
+			return;
+		}
+		textModified = false;
 		// Update global history
 		String[] globalItems = readExpressionHistory(fExpressionHistoryDialogSettings);
 		if (globalItems.length > 0 && newItem.equals(globalItems[0])) {
@@ -233,51 +236,19 @@
 	 *            the dialog settings
 	 */
 	private static void storeExpressionHistory(String[] expressions, IDialogSettings dialogSettings) {
-		int length = Math.min(expressions.length, MAX_HISTORY_SIZE);
+		List<String> uniqueExpressions = new ArrayList<>(new LinkedHashSet<>(Arrays.asList(expressions)));
+		final int length = Math.min(uniqueExpressions.size(), MAX_HISTORY_SIZE);
 		int count = 0;
-		outer: for (int i = 0; i < length; i++) {
-			for (int j = 0; j < i; j++) {
-				if (expressions[i].equals(expressions[j])) {
-					break outer;
-				}
+		for (String expression : uniqueExpressions) {
+			dialogSettings.put(DS_KEY_HISTORY_ENTRY_PREFIX + count, expression);
+			count++;
+			if (count >= length) {
+				break;
 			}
-			dialogSettings.put(DS_KEY_HISTORY_ENTRY_PREFIX + count, expressions[i]);
-			count = count + 1;
 		}
 		dialogSettings.put(DS_KEY_HISTORY_ENTRY_COUNT, count);
 	}
 
-	/**
-	 * Returns the label for the history separator.
-	 *
-	 * @return the label for the history separator
-	 */
-	private String getSeparatorLabel() {
-		int borderWidth = fExpressionHistory.computeTrim(0, 0, 0, 0).width;
-		Rectangle rect = fExpressionHistory.getBounds();
-		int width = rect.width - borderWidth;
-
-		GC gc = new GC(fExpressionHistory);
-		gc.setFont(fExpressionHistory.getFont());
-
-		int fSeparatorWidth = gc.getAdvanceWidth('-');
-		String separatorLabel = PropertyPageMessages.JavaVariableDetailsPane_historySeparator;
-		int fMessageLength = gc.textExtent(separatorLabel).x;
-
-		gc.dispose();
-
-		StringBuilder dashes = new StringBuilder();
-		int chars = (((width - fMessageLength) / fSeparatorWidth) / 2) - 2;
-		for (int i = 0; i < chars; i++) {
-			dashes.append('-');
-		}
-
-		StringBuilder result = new StringBuilder();
-		result.append(dashes);
-		result.append(" " + separatorLabel + " "); //$NON-NLS-1$//$NON-NLS-2$
-		result.append(dashes);
-		return result.toString().trim();
-	}
 
 	@Override
 	public String getDescription() {
@@ -324,9 +295,6 @@
 		if (fExpressionHistory != null) {
 			fExpressionHistory.dispose();
 		}
-		if (fLocalExpressionHistory != null) {
-			fLocalExpressionHistory.clear();
-		}
 		if (focusListener != null && getSourceViewer() != null && getSourceViewer().getTextWidget() != null) {
 			getSourceViewer().getTextWidget().removeFocusListener(focusListener);
 		}
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java
index 4b32c69..0bd9d04 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java
@@ -259,10 +259,8 @@
 
 	/**
 	 * Request to stops this thread with the given exception.<br>
-	 * The result will be the same as calling
-	 * java.lang.Thread#stop(java.lang.Throwable).<br>
-	 * If the thread is suspended when the method is called, the thread must be
-	 * resumed to complete the action.<br>
+	 * The result will be the same as calling java.lang.Thread#stop(java.lang.Throwable).<br>
+	 * If the thread is suspended when the method is called, the thread must be resumed to complete the action.<br>
 	 *
 	 * <em>exception</em> must represent an exception.
 	 *
@@ -271,7 +269,7 @@
 	 * @exception DebugException
 	 *                if the request fails
 	 * @since 3.0
-	 * @see java.lang.Thread#stop(java.lang.Throwable)
+	 * @see java.lang.Thread#stop()
 	 */
 	public void stop(IJavaObject exception) throws DebugException;
 
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupUtil.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupUtil.java
index 0639828..cbbbe50 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupUtil.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/internal/launching/JavaSourceLookupUtil.java
@@ -62,29 +62,7 @@
 					} else {
 						IPackageFragmentRoot root = getPackageFragmentRoot(entry);
 						if (root == null) {
-							String path = entry.getSourceAttachmentLocation();
-							ISourceContainer container = null;
-							if (path == null) {
-								// use the archive itself
-								path = entry.getLocation();
-							}
-							if (path != null) {
-								// check if file or folder
-								File file = new File(path);
-								if (file.isDirectory()) {
-									IResource resource = entry.getResource();
-									if (resource instanceof IContainer) {
-										container = new FolderSourceContainer((IContainer) resource, false);
-									} else {
-										container = new DirectorySourceContainer(file, false);
-									}
-								} else {
-									container = new ExternalArchiveSourceContainer(path, true);
-								}
-								if (!containers.contains(container)) {
-									containers.add(container);
-								}
-							}
+							addSourceAttachment(entry, containers);
 						} else {
 							ISourceContainer container = new PackageFragmentRootSourceContainer(root);
 							if (!containers.contains(container)) {
@@ -117,6 +95,39 @@
 	}
 
 	/**
+	 * Tries to find and attach source containers for given runtime classpath entry
+	 *
+	 * @param entry
+	 *            non null
+	 * @param containers
+	 */
+	private static void addSourceAttachment(IRuntimeClasspathEntry entry, List<ISourceContainer> containers) {
+		String path = entry.getSourceAttachmentLocation();
+		ISourceContainer container = null;
+		if (path == null) {
+			// use the archive itself
+			path = entry.getLocation();
+		}
+		if (path != null) {
+			// check if file or folder
+			File file = new File(path);
+			if (file.isDirectory()) {
+				IResource resource = entry.getResource();
+				if (resource instanceof IContainer) {
+					container = new FolderSourceContainer((IContainer) resource, false);
+				} else {
+					container = new DirectorySourceContainer(file, false);
+				}
+			} else {
+				container = new ExternalArchiveSourceContainer(path, true);
+			}
+			if (!containers.contains(container)) {
+				containers.add(container);
+			}
+		}
+	}
+
+	/**
 	 * Returns whether the source attachments of the given package fragment
 	 * root and runtime classpath entry are equal.
 	 * <p>
@@ -212,6 +223,7 @@
 	private static void getPackageFragmentRootContainers(IRuntimeClasspathEntry entry, List<ISourceContainer> containers) {
 		IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
 		IPath entryPath = entry.getPath();
+		boolean found = false;
 		try {
 			IJavaProject[] jps = model.getJavaProjects();
 			for (int i = 0; i < jps.length; i++) {
@@ -225,6 +237,7 @@
 							PackageFragmentRootSourceContainer container = new PackageFragmentRootSourceContainer(root);
 							if (!containers.contains(container)) {
 								containers.add(container);
+								found = true;
 							}
 						}
 					}
@@ -234,5 +247,9 @@
 		catch (JavaModelException e) {
 			LaunchingPlugin.log(e);
 		}
+
+		if (!found) {
+			addSourceAttachment(entry, containers);
+		}
 	}
 }
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 94e64da..25f6407 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -133,10 +133,11 @@
 
 	/**
 	 * The list of locations in which to look for the java executable in candidate
-	 * VM install locations, relative to the VM install location.
+	 * VM install locations, relative to the VM install location. From Java 9 onwards, there may not be a jre directory.
 	 */
 	private static final String[] fgCandidateJavaFiles = {"javaw", "javaw.exe", "java", "java.exe", "j9w", "j9w.exe", "j9", "j9.exe"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
-	private static final String[] fgCandidateJavaLocations = {"bin" + File.separatorChar, JRE + File.separatorChar + "bin" + File.separatorChar}; //$NON-NLS-1$ //$NON-NLS-2$
+	private static final String[] fgCandidateJavaLocations = { File.separator, "bin" + File.separatorChar, //$NON-NLS-1$
+			JRE + File.separatorChar + "bin" + File.separatorChar };//$NON-NLS-1$
 
 	private static ILibraryLocationResolver[] fgLibraryLocationResolvers = null;
 
@@ -150,8 +151,19 @@
 	public static File findJavaExecutable(File vmInstallLocation) {
 		// Try each candidate in order.  The first one found wins.  Thus, the order
 		// of fgCandidateJavaLocations and fgCandidateJavaFiles is significant.
+
+		boolean isBin = false;
+		String filePath = vmInstallLocation.getPath();
+		int index = filePath.lastIndexOf(File.separatorChar);
+		if (index > 0 && filePath.substring(index + 1).equals("bin")) { //$NON-NLS-1$
+			isBin = true;
+		}
 		for (int i = 0; i < fgCandidateJavaFiles.length; i++) {
 			for (int j = 0; j < fgCandidateJavaLocations.length; j++) {
+				if (!isBin && j == 0) {
+					// search in "." only under bin for java executables for Java 9 and above
+					continue;
+				}
 				File javaFile = new File(vmInstallLocation, fgCandidateJavaLocations[j] + fgCandidateJavaFiles[i]);
 				if (javaFile.isFile()) {
 					return javaFile;
@@ -648,7 +660,9 @@
 		if (javaExecutable == null) {
 			status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_Not_a_JDK_Root__Java_executable_was_not_found_1, null); //
 		} else {
-			if (canDetectDefaultSystemLibraries(javaHome, javaExecutable)) {
+			File javaHomeNew = javaHome;
+
+			if (canDetectDefaultSystemLibraries(javaHomeNew, javaExecutable)) {
 				status = new Status(IStatus.OK, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_ok_2, null);
 			} else {
 				status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_Not_a_JDK_root__System_library_was_not_found__1, null);
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 d2fbe86..b2e296f 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
@@ -93,12 +93,9 @@
 		// VM-specific attributes
 		Map<String, Object> vmAttributesMap = getVMSpecificAttributesMap(configuration);
 
-		String[][] paths = getClasspathAndModulepath(configuration);
-		if (paths == null || paths.length == 0) {
-			return null;
-		}
 		// Create VM config
-		VMRunnerConfiguration runConfig = new VMRunnerConfiguration(mainTypeName, paths[0]);
+		// Bug 529435 :to move to getClasspathAndModulepath after java 8 is sunset
+		VMRunnerConfiguration runConfig = new VMRunnerConfiguration(mainTypeName, getClasspath(configuration));
 		runConfig.setProgramArguments(execArgs.getProgramArgumentsArray());
 		runConfig.setEnvironment(envp);
 		runConfig.setVMArguments(execArgs.getVMArgumentsArray());
@@ -127,7 +124,8 @@
 			runConfig.setBootClassPath(getBootpath(configuration));
 		} else if (supportsModule()) {
 			// module path
-			if (paths.length > 1) {
+			String[][] paths = getClasspathAndModulepath(configuration);
+			if (paths != null && paths.length > 1) {
 				runConfig.setModulepath(paths[1]);
 			}
 			if (!configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_MODULE_CLI_OPTIONS, true)) {
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 6156c48..1b637af 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
@@ -28,6 +28,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
@@ -3485,8 +3486,7 @@
 		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> defaultModules = getDefaultModules(allSystemRoots);
 			Set<String> limit = new HashSet<>(defaultModules);
 			if (limit.retainAll(selected)) { // limit = selected ∩ default -- only add the option, if limit ⊂ default
 				if (limit.isEmpty()) {
@@ -3506,6 +3506,31 @@
 		}
 	}
 
+	private static Set<String> getDefaultModules(List<IPackageFragmentRoot> allSystemRoots) throws JavaModelException {
+		HashMap<String, String[]> moduleDescriptions = new HashMap<>();
+		for (IPackageFragmentRoot packageFragmentRoot : allSystemRoots) {
+			IModuleDescription module = packageFragmentRoot.getModuleDescription();
+			if (module != null) {
+				moduleDescriptions.put(module.getElementName(), module.getRequiredModuleNames());
+			}
+		}
+		HashSet<String> result = new HashSet<>();
+		HashSet<String> todo = new HashSet<>(JavaProject.defaultRootModules(allSystemRoots));
+		while (!todo.isEmpty()) {
+			HashSet<String> more = new HashSet<>();
+			for (String s : todo) {
+				if (result.add(s)) {
+					String[] requiredModules = moduleDescriptions.get(s);
+					if (requiredModules != null) {
+						Collections.addAll(more, requiredModules);
+					}
+				}
+			}
+			todo = more;
+		}
+		return result;
+	}
+
 	private static String joinedSortedList(Collection<String> list) {
 		String[] limitArray = list.toArray(new String[list.size()]);
 		Arrays.sort(limitArray);