/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Jesper Steen Moller - enhancement 254677 - filter getters/setters
 *     Andrey Loskutov <loskutov@gmx.de> - bug 5188 - breakpoint filtering
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.core.model;

import java.io.IOException;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
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.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.IBreakpointManagerListener;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.ISuspendResume;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdi.TimeoutException;
import org.eclipse.jdi.internal.VirtualMachineImpl;
import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameMatch;
import org.eclipse.jdt.core.search.TypeNameMatchRequestor;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaHotCodeReplaceListener;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaThreadGroup;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.debug.eval.EvaluationManager;
import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
import org.eclipse.jdt.internal.debug.core.EventDispatcher;
import org.eclipse.jdt.internal.debug.core.IJDIEventListener;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint;
import org.eclipse.jdt.internal.debug.core.breakpoints.JavaLineBreakpoint;

import com.sun.jdi.ClassType;
import com.sun.jdi.InternalException;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadGroupReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.LocatableEvent;
import com.sun.jdi.event.ThreadDeathEvent;
import com.sun.jdi.event.ThreadStartEvent;
import com.sun.jdi.event.VMDeathEvent;
import com.sun.jdi.event.VMDisconnectEvent;
import com.sun.jdi.event.VMStartEvent;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;

/**
 * Debug target for JDI debug model.
 */
public class JDIDebugTarget extends JDIDebugElement implements
		IJavaDebugTarget, ILaunchListener, IBreakpointManagerListener,
		IDebugEventSetListener {

	/**
	 * Threads contained in this debug target. When a thread starts it is added
	 * to the list. When a thread ends it is removed from the list.
	 *
	 * TODO investigate making this a synchronized collection, to remove all this copying
	 * @see #getThreadIterator()
	 */
	private List<JDIThread> fThreads;

	/**
	 * List of thread groups in this target.
	 */
	private List<JDIThreadGroup> fGroups;

	/**
	 * Associated system process, or <code>null</code> if not available.
	 */
	private IProcess fProcess;
	/**
	 * Underlying virtual machine.
	 */
	private VirtualMachine fVirtualMachine;
	/**
	 * Whether terminate is supported. Not all targets support terminate. For
	 * example, a VM that was attached to remotely may not allow the user to
	 * terminate it.
	 */
	private boolean fSupportsTerminate;
	/**
	 * Whether terminated
	 */
	private boolean fTerminated;

	/**
	 * Whether in the process of terminating
	 */
	private boolean fTerminating;

	/**
	 * Whether in the process of disconnecting
	 */
	private boolean fDisconnecting;

	/**
	 * Whether disconnected
	 */
	private boolean fDisconnected;
	/**
	 * Whether disconnect is supported.
	 */
	private boolean fSupportsDisconnect;
	/**
	 * Whether enable/disable object GC is allowed
	 */
	private boolean fSupportsDisableGC;
	/**
	 * Collection of breakpoints added to this target. Values are of type
	 * <code>IJavaBreakpoint</code>.
	 */
	private List<IBreakpoint> fBreakpoints;

	/**
	 * Collection of types that have attempted HCR, but failed. The types are
	 * stored by their fully qualified names.
	 */
	private Set<String> fOutOfSynchTypes;
	/**
	 * Whether or not this target has performed a hot code replace.
	 */
	private boolean fHasHCROccurred;

	/**
	 * The name of this target - set by the client on creation, or retrieved
	 * from the underlying VM.
	 */
	private String fName;

	/**
	 * The event dispatcher for this debug target, which runs in its own thread.
	 */
	private EventDispatcher fEventDispatcher;

	/**
	 * The thread start event handler
	 */
	private ThreadStartHandler fThreadStartHandler;

	/**
	 * Handles changes in thread names, detected via a breakpoint in {@link java.lang.Thread#setName(String)}.
	 */
	private ThreadNameChangeHandler fThreadNameChangeHandler;

	/**
	 * Whether this VM is suspended.
	 */
	private boolean fSuspended = true;

	/**
	 * Whether the VM should be resumed on startup
	 */
	private boolean fResumeOnStartup;

	/**
	 * The launch this target is contained in
	 */
	private ILaunch fLaunch;

	/**
	 * Count of the number of suspend events in this target
	 */
	private int fSuspendCount;

	/**
	 * Evaluation engine cache by Java project. Engines are disposed when this
	 * target terminates.
	 */
	private Map<IJavaProject, IAstEvaluationEngine> fEngines;

	/**
	 * List of step filters - each string is a pattern/fully qualified name of a
	 * type to filter.
	 */
	private String[] fStepFilters;

	/**
	 * Step filter state mask.
	 */
	private int fStepFilterMask;

	/**
	 * Step filter bit mask - indicates if step filters are enabled.
	 */
	private static final int STEP_FILTERS_ENABLED = 0x001;

	/**
	 * Step filter bit mask - indicates if synthetic methods are filtered.
	 */
	private static final int FILTER_SYNTHETICS = 0x002;

	/**
	 * Step filter bit mask - indicates if static initializers are filtered.
	 */
	private static final int FILTER_STATIC_INITIALIZERS = 0x004;

	/**
	 * Step filter bit mask - indicates if constructors are filtered.
	 */
	private static final int FILTER_CONSTRUCTORS = 0x008;

	/**
	 * When a step lands in a filtered location, this indicates whether stepping
	 * should proceed "through" to an unfiltered location or step return.
	 *
	 * @since 3.3
	 */
	private static final int STEP_THRU_FILTERS = 0x010;

	/**
	 * Step filter bit mask - indicates if simple getters are filtered.
	 *
	 * @since 3.7
	 */
	private static final int FILTER_GETTERS = 0x020;

	/**
	 * Step filter bit mask - indicates if simple setters are filtered.
	 *
	 * @since 3.7
	 */
	private static final int FILTER_SETTERS = 0x040;

	/**
	 * Mask used to flip individual bit masks via XOR
	 */
	private static final int XOR_MASK = 0xFFF;
	/**
	 * Whether this debug target is currently performing a hot code replace
	 */
	private boolean fIsPerformingHotCodeReplace;

	/**
	 * Target specific HCR listeners
	 *
	 * @since 3.6
	 */
	private ListenerList<IJavaHotCodeReplaceListener> fHCRListeners = new ListenerList<>();

	/**
	 * Java scope of the current launch, "null" means everything is in scope
	 */
	private IJavaSearchScope fScope;

	/**
	 * Java projects of the current launch, "null" means everything is in scope
	 */
	private Set<IProject> fProjects;

	/**
	 * Java types from breakpoints with the flag if they are in scope for current launch
	 */
	private Map<String, Boolean> fKnownTypes = new HashMap<>();

	/**
	 * Creates a new JDI debug target for the given virtual machine.
	 *
	 * @param jvm
	 *            the underlying VM
	 * @param name
	 *            the name to use for this VM, or <code>null</code> if the name
	 *            should be retrieved from the underlying VM
	 * @param supportsTerminate
	 *            whether the terminate action is supported by this debug target
	 * @param supportsDisconnect
	 *            whether the disconnect action is supported by this debug
	 *            target
	 * @param process
	 *            the system process associated with the underlying VM, or
	 *            <code>null</code> if no system process is available (for
	 *            example, a remote VM)
	 * @param resume
	 *            whether the VM should be resumed on startup. Has no effect if
	 *            the VM is already resumed/running when the connection is made.
	 */
	public JDIDebugTarget(ILaunch launch, VirtualMachine jvm, String name,
			boolean supportTerminate, boolean supportDisconnect,
			IProcess process, boolean resume) {
		super(null);
		setLaunch(launch);
		setResumeOnStartup(resume);
		setSupportsTerminate(supportTerminate);
		setSupportsDisconnect(supportDisconnect);
		setVM(jvm);
		jvm.setDebugTraceMode(VirtualMachine.TRACE_NONE);
		setProcess(process);
		setTerminated(false);
		setTerminating(false);
		setDisconnected(false);
		setDisconnecting(false);
		setName(name);
		prepareBreakpointsSearchScope();
		setBreakpoints(new ArrayList<>(5));
		setThreadList(new ArrayList<>());
		fGroups = new ArrayList<>(5);
		setOutOfSynchTypes(new ArrayList<>(0));
		setHCROccurred(false);
		initialize();
		DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
		DebugPlugin.getDefault().getBreakpointManager()
				.addBreakpointManagerListener(this);
	}


	private void prepareBreakpointsSearchScope() {
		boolean enableFiltering = Platform.getPreferencesService().getBoolean(
				JDIDebugPlugin.getUniqueIdentifier(),
				JDIDebugModel.PREF_FILTER_BREAKPOINTS_FROM_UNRELATED_SOURCES,
				true,
				null);
		ILaunchConfiguration config = getLaunch().getLaunchConfiguration();
		if (!enableFiltering || config == null) {
			return;
		}
		try {
			// See IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH
			boolean defaultClasspath = config.getAttribute("org.eclipse.jdt.launching.DEFAULT_CLASSPATH", true); //$NON-NLS-1$
			if(!defaultClasspath){
				return;
			}

			IResource[] resources = config.getMappedResources();
			if (resources != null && resources.length != 0) {
				Set<IJavaProject> javaProjects = getJavaProjects(resources);
				fProjects = collectReferencedJavaProjects(javaProjects);
				fScope = createSourcesOnlyScope();
				return;
			}
			// See IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME
			String projectName = config.getAttribute("org.eclipse.jdt.launching.PROJECT_ATTR", (String)null); //$NON-NLS-1$
			if(projectName != null && !projectName.isEmpty()){
				Set<IJavaProject> javaProjects = getJavaProjects(ResourcesPlugin.getWorkspace().getRoot().getProject(projectName));
				fProjects = collectReferencedJavaProjects(javaProjects);
				fScope = createSourcesOnlyScope();
				return;
			}
		} catch (CoreException e) {
			logError(e);
		}
	}

	private IJavaSearchScope createSourcesOnlyScope() {
		int includeMask = IJavaSearchScope.SOURCES;
		Set<IJavaProject> javaProjects = getJavaProjects(ResourcesPlugin.getWorkspace().getRoot().getProjects());
		return SearchEngine.createJavaSearchScope(javaProjects.toArray(new IJavaElement[javaProjects.size()]), includeMask);
	}

	/**
	 * Returns the event dispatcher for this debug target. There is one event
	 * dispatcher per debug target.
	 *
	 * @return event dispatcher
	 */
	public EventDispatcher getEventDispatcher() {
		return fEventDispatcher;
	}

	/**
	 * Sets the event dispatcher for this debug target. Set once at
	 * initialization.
	 *
	 * @param dispatcher
	 *            event dispatcher
	 * @see #initialize()
	 */
	private void setEventDispatcher(EventDispatcher dispatcher) {
		fEventDispatcher = dispatcher;
	}

	/**
	 * Returns an iterator over the collection of threads. The returned iterator
	 * is made on a copy of the thread list so that it is thread safe. This
	 * method should always be used instead of getThreadList().iterator()
	 *
	 * @return an iterator over the collection of threads
	 */
	private Iterator<JDIThread> getThreadIterator() {
		List<JDIThread> threadList;
		synchronized (fThreads) {
			//TODO investigate making fThreads be a synchronized collection, to remove all this copying
			threadList = new ArrayList<>(fThreads);
		}
		return threadList.iterator();
	}

	/**
	 * Sets the list of threads contained in this debug target. Set to an empty
	 * collection on creation. Threads are added and removed as they start and
	 * end. On termination this collection is set to the immutable singleton
	 * empty list.
	 *
	 * @param threads
	 *            empty list
	 */
	private void setThreadList(List<JDIThread> threads) {
		fThreads = threads;
	}

	/**
	 * Returns the collection of breakpoints installed in this debug target.
	 *
	 * @return list of installed breakpoints - instances of
	 *         <code>IJavaBreakpoint</code>
	 */
	public List<IBreakpoint> getBreakpoints() {
		return fBreakpoints;
	}

	/**
	 * Sets the list of breakpoints installed in this debug target. Set to an
	 * empty list on creation.
	 *
	 * @param breakpoints
	 *            empty list
	 */
	private void setBreakpoints(List<IBreakpoint> breakpoints) {
		fBreakpoints = breakpoints;
	}

	/**
	 * Notifies this target that the underlying VM has started. This is the
	 * first event received from the VM. The VM is resumed. This event is not
	 * generated when an attach is made to a VM that is already running (has
	 * already started up). The VM is resumed as specified on creation.
	 *
	 * @param event
	 *            VM start event
	 */
	public void handleVMStart(VMStartEvent event) {
		if (isResumeOnStartup()) {
			try {
				setSuspended(true);
				resume();
			} catch (DebugException e) {
				logError(e);
			}
		}
		// If any threads have resumed since thread collection was initialized,
		// update their status (avoid concurrent modification - use
		// #getThreads())
		IThread[] threads = getThreads();
		for (IThread thread2 : threads) {
			JDIThread thread = (JDIThread) thread2;
			if (thread.isSuspended()) {
				try {
					boolean suspended = thread.getUnderlyingThread()
							.isSuspended();
					if (!suspended) {
						thread.setRunning(true);
						thread.fireResumeEvent(DebugEvent.CLIENT_REQUEST);
					}
				} catch (VMDisconnectedException e) {
				} catch (ObjectCollectedException e) {
				} catch (RuntimeException e) {
					logError(e);
				}
			}
		}

	}

	/**
	 * Initialize event requests and state from the underlying VM. This method
	 * is synchronized to ensure that we do not start to process an events from
	 * the target until our state is initialized.
	 */
	protected synchronized void initialize() {
		setEventDispatcher(new EventDispatcher(this));
		setRequestTimeout(Platform.getPreferencesService().getInt(
				JDIDebugPlugin.getUniqueIdentifier(),
				JDIDebugModel.PREF_REQUEST_TIMEOUT,
				JDIDebugModel.DEF_REQUEST_TIMEOUT,
				null));
		initializeRequests();
		initializeState();
		initializeBreakpoints();
		getLaunch().addDebugTarget(this);
		DebugPlugin plugin = DebugPlugin.getDefault();
		plugin.addDebugEventListener(this);
		fireCreationEvent();
		// begin handling/dispatching events after the creation event is handled
		// by all listeners
		plugin.asyncExec(new Runnable() {
			@Override
			public void run() {
				EventDispatcher dispatcher = getEventDispatcher();
				if (dispatcher != null) {
					Thread t = new Thread(
							dispatcher,
							JDIDebugModel.getPluginIdentifier()
									+ JDIDebugModelMessages.JDIDebugTarget_JDI_Event_Dispatcher);
					t.setDaemon(true);
					t.start();
				}
			}
		});
	}

	/**
	 * Adds all of the pre-existing threads to this debug target.
	 */
	protected void initializeState() {

		List<ThreadReference> threads = null;
		VirtualMachine vm = getVM();
		if (vm != null) {
			try {
				String name = vm.name();
				fSupportsDisableGC = !name.equals("Classic VM"); //$NON-NLS-1$
			} catch (RuntimeException e) {
				internalError(e);
			}
			try {
				threads = vm.allThreads();
			} catch (RuntimeException e) {
				internalError(e);
			}
			if (threads != null) {
				Iterator<ThreadReference> initialThreads = threads.iterator();
				while (initialThreads.hasNext()) {
					createThread(initialThreads.next());
				}
			}
		}

		if (isResumeOnStartup()) {
			setSuspended(false);
		}
	}

	/**
	 * Registers event handlers for thread creation, thread termination.
	 */
	protected void initializeRequests() {
		setThreadStartHandler(new ThreadStartHandler());
		setThreadNameChangeHandler(new ThreadNameChangeHandler());
		new ThreadDeathHandler();
	}

	/**
	 * Installs all Java breakpoints that currently exist in the breakpoint
	 * manager
	 */
	protected void initializeBreakpoints() {
		IBreakpointManager manager = DebugPlugin.getDefault()
				.getBreakpointManager();
		manager.addBreakpointListener(this);
		IBreakpoint[] bps = manager.getBreakpoints(JDIDebugModel
				.getPluginIdentifier());
		for (IBreakpoint bp : bps) {
			if (bp instanceof IJavaBreakpoint) {
				breakpointAdded(bp);
			}
		}
	}

	/**
	 * Creates, adds and returns a thread for the given underlying thread
	 * reference. A creation event is fired for the thread. Returns
	 * <code>null</code> if during the creation of the thread this target is set
	 * to the disconnected state.
	 *
	 * @param thread
	 *            underlying thread
	 * @return model thread
	 */
	protected JDIThread createThread(ThreadReference thread) {
		JDIThread jdiThread = newThread(thread);
		if (jdiThread == null) {
			return null;
		}
		if (isDisconnected()) {
			return null;
		}
		synchronized (fThreads) {
			fThreads.add(jdiThread);
		}
		jdiThread.fireCreationEvent();
		return jdiThread;
	}

	/**
	 * Factory method for creating new threads. Creates and returns a new thread
	 * object for the underlying thread reference, or <code>null</code> if none
	 *
	 * @param reference
	 *            thread reference
	 * @return JDI model thread
	 */
	protected JDIThread newThread(ThreadReference reference) {
		try {
			return new JDIThread(this, reference);
		} catch (ObjectCollectedException exception) {
			// ObjectCollectionException can be thrown if the thread has already
			// completed (exited) in the VM.
		}
		return null;
	}

	@Override
	public IThread[] getThreads() {
		synchronized (fThreads) {
			IThread[] threads = new IThread[fThreads.size()];
			int index = 0;
			for (JDIThread thread : fThreads) {
				if (!thread.isSystemThread()) {
					threads[index] = thread;
					++index;
				}
			}
			for (JDIThread thread : fThreads) {
				if (thread.isSystemThread()) {
					threads[index] = thread;
					++index;
				}
			}
			return threads;
		}
	}

	@Override
	public boolean canResume() {
		return (isSuspended() || canResumeThreads()) && isAvailable()
				&& !isPerformingHotCodeReplace();
	}

	/**
	 * Returns whether this target has any threads which can be resumed.
	 *
	 * @return true if any thread can be resumed, false otherwise
	 * @since 3.2
	 */
	private boolean canResumeThreads() {
		Iterator<JDIThread> it = getThreadIterator();
		while (it.hasNext()) {
			IThread thread = it.next();
			if (thread.canResume()) {
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean canSuspend() {
		if (isAvailable()) {
			// allow suspend when one or more threads are currently running
			IThread[] threads = getThreads();
			for (IThread thread : threads) {
				if (((JDIThread) thread).canSuspend()) {
					return true;
				}
			}
			return !isSuspended();
		}
		return false;
	}

	@Override
	public boolean canTerminate() {
		return supportsTerminate() && isAvailable();
	}

	@Override
	public boolean canDisconnect() {
		return supportsDisconnect() && !isDisconnected();
	}

	/**
	 * Returns whether this debug target supports disconnecting.
	 *
	 * @return whether this debug target supports disconnecting
	 */
	protected boolean supportsDisconnect() {
		return fSupportsDisconnect;
	}

	/**
	 * Sets whether this debug target supports disconnection. Set on creation.
	 *
	 * @param supported
	 *            <code>true</code> if this target supports disconnection,
	 *            otherwise <code>false</code>
	 */
	private void setSupportsDisconnect(boolean supported) {
		fSupportsDisconnect = supported;
	}

	/**
	 * Returns whether this debug target supports termination.
	 *
	 * @return whether this debug target supports termination
	 */
	protected boolean supportsTerminate() {
		return fSupportsTerminate;
	}

	/**
	 * Sets whether this debug target supports termination. Set on creation.
	 *
	 * @param supported
	 *            <code>true</code> if this target supports termination,
	 *            otherwise <code>false</code>
	 */
	private void setSupportsTerminate(boolean supported) {
		fSupportsTerminate = supported;
	}

	@Override
	public boolean supportsHotCodeReplace() {
		return supportsJ9HotCodeReplace() || supportsJDKHotCodeReplace();
	}

	@Override
	public boolean supportsInstanceBreakpoints() {
		if (isAvailable()
				&& JDIDebugPlugin.isJdiVersionGreaterThanOrEqual(new int[] { 1,
						4 })) {
			VirtualMachine vm = getVM();
			if (vm != null) {
				return vm.canUseInstanceFilters();
			}
		}
		return false;
	}

	/**
	 * Returns whether this debug target supports hot code replace for the J9
	 * VM.
	 *
	 * @return whether this debug target supports J9 hot code replace
	 */
	public boolean supportsJ9HotCodeReplace() {
		VirtualMachine vm = getVM();
		if (isAvailable() && vm instanceof org.eclipse.jdi.hcr.VirtualMachine) {
			try {
				return ((org.eclipse.jdi.hcr.VirtualMachine) vm)
						.canReloadClasses();
			} catch (UnsupportedOperationException e) {
				// This is not an error condition -
				// UnsupportedOperationException is thrown when a VM does
				// not support HCR
			}
		}
		return false;
	}

	/**
	 * Returns whether this debug target supports hot code replace for JDK VMs.
	 *
	 * @return whether this debug target supports JDK hot code replace
	 */
	public boolean supportsJDKHotCodeReplace() {
		if (isAvailable()
				&& JDIDebugPlugin.isJdiVersionGreaterThanOrEqual(new int[] { 1,
						4 })) {
			VirtualMachine vm = getVM();
			if (vm != null) {
				return vm.canRedefineClasses();
			}
		}
		return false;
	}

	/**
	 * Returns whether this debug target supports popping stack frames.
	 *
	 * @return whether this debug target supports popping stack frames.
	 */
	public boolean canPopFrames() {
		if (isAvailable()
				&& JDIDebugPlugin.isJdiVersionGreaterThanOrEqual(new int[] { 1,
						4 })) {
			VirtualMachine vm = getVM();
			if (vm != null) {
				return vm.canPopFrames();
			}
		}
		return false;
	}

	@Override
	public void disconnect() throws DebugException {

		if (!isAvailable()) {
			// already done
			return;
		}

		if (!canDisconnect()) {
			notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_disconnect);
		}

		try {
			setDisconnecting(true);
			disposeThreadHandlers();
			VirtualMachine vm = getVM();
			if (vm != null) {
				vm.dispose();
			}
		} catch (VMDisconnectedException e) {
			// if the VM disconnects while disconnecting, perform
			// normal disconnect handling
			disconnected();
		} catch (RuntimeException e) {
			targetRequestFailed(
					MessageFormat.format(
							JDIDebugModelMessages.JDIDebugTarget_exception_disconnecting,
							e.toString()), e);
		}

	}

	/**
	 * Allows for ThreadStartHandler to do clean up/disposal.
	 */
	private void disposeThreadHandlers() {
		ThreadStartHandler handler = getThreadStartHandler();
		if (handler != null) {
			handler.deleteRequest();
		}
		ThreadNameChangeHandler nameChangeHandler = getThreadNameChangeHandler();
		if (nameChangeHandler != null) {
			nameChangeHandler.deleteRequest();
		}
	}

	/**
	 * Returns the underlying virtual machine associated with this debug target,
	 * or <code>null</code> if none (disconnected/terminated)
	 *
	 * @return the underlying VM or <code>null</code>
	 */
	@Override
	public VirtualMachine getVM() {
		return fVirtualMachine;
	}

	/**
	 * Sets the underlying VM associated with this debug target. Set on
	 * creation.
	 *
	 * @param vm
	 *            underlying VM
	 */
	private void setVM(VirtualMachine vm) {
		fVirtualMachine = vm;
	}

	/**
	 * Sets whether this debug target has performed a hot code replace.
	 */
	public void setHCROccurred(boolean occurred) {
		fHasHCROccurred = occurred;
	}

	public void removeOutOfSynchTypes(List<String> qualifiedNames) {
		fOutOfSynchTypes.removeAll(qualifiedNames);
	}

	/**
	 * Sets the list of out of synch types to the given list.
	 */
	private void setOutOfSynchTypes(List<String> qualifiedNames) {
		fOutOfSynchTypes = new HashSet<>();
		fOutOfSynchTypes.addAll(qualifiedNames);
	}

	/**
	 * The given types have failed to be reloaded by HCR. Add them to the list
	 * of out of synch types.
	 */
	public void addOutOfSynchTypes(List<String> qualifiedNames) {
		fOutOfSynchTypes.addAll(qualifiedNames);
	}

	/**
	 * Returns whether the given type is out of synch in this target.
	 */
	public boolean isOutOfSynch(String qualifiedName) {
		if (fOutOfSynchTypes == null || fOutOfSynchTypes.isEmpty()) {
			return false;
		}
		return fOutOfSynchTypes.contains(qualifiedName);
	}

	@Override
	public boolean isOutOfSynch() throws DebugException {
		Iterator<JDIThread> threads = getThreadIterator();
		while (threads.hasNext()) {
			JDIThread thread = threads.next();
			if (thread.isOutOfSynch()) {
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean mayBeOutOfSynch() {
		Iterator<JDIThread> threads = getThreadIterator();
		while (threads.hasNext()) {
			JDIThread thread = threads.next();
			if (thread.mayBeOutOfSynch()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns whether a hot code replace attempt has failed.
	 *
	 * HCR has failed if there are any out of synch types
	 */
	public boolean hasHCRFailed() {
		return fOutOfSynchTypes != null && !fOutOfSynchTypes.isEmpty();
	}

	/**
	 * Returns whether this debug target has performed a hot code replace
	 */
	public boolean hasHCROccurred() {
		return fHasHCROccurred;
	}

	/**
	 * Reinstall all breakpoints installed in the given resources
	 * @param resources
	 * @param classNames
	 */
	public void reinstallBreakpointsIn(List<IResource> resources, List<String> classNames) {
		List<IBreakpoint> breakpoints = getBreakpoints();
		IJavaBreakpoint[] copy = new IJavaBreakpoint[breakpoints.size()];
		breakpoints.toArray(copy);
		IJavaBreakpoint breakpoint = null;
		String installedType = null;

		for (IJavaBreakpoint element : copy) {
			breakpoint = element;
			if (breakpoint instanceof JavaLineBreakpoint) {
				try {
					installedType = breakpoint.getTypeName();
					if (classNames.contains(installedType)) {
						breakpointRemoved(breakpoint, null);
						breakpointAdded(breakpoint);
					}
				} catch (CoreException ce) {
					logError(ce);
					continue;
				}
			}
		}
	}

	/**
	 * Finds and returns the JDI thread for the associated thread reference, or
	 * <code>null</code> if not found.
	 *
	 * @param the
	 *            underlying thread reference
	 * @return the associated model thread
	 */
	public JDIThread findThread(ThreadReference tr) {
		Iterator<JDIThread> iter = getThreadIterator();
		while (iter.hasNext()) {
			JDIThread thread = iter.next();
			if (thread.getUnderlyingThread().equals(tr)) {
				return thread;
			}
		}
		return null;
	}

	@Override
	public String getName() throws DebugException {
		if (fName == null) {
			setName(getVMName());
		}
		return fName;
	}

	/**
	 * Sets the name of this debug target. Set on creation, and if set to
	 * <code>null</code> the name will be retrieved lazily from the underlying
	 * VM.
	 *
	 * @param name
	 *            the name of this VM or <code>null</code> if the name should be
	 *            retrieved from the underlying VM
	 */
	protected void setName(String name) {
		fName = name;
	}

	/**
	 * Sets the process associated with this debug target, possibly
	 * <code>null</code>. Set on creation.
	 *
	 * @param process
	 *            the system process associated with the underlying VM, or
	 *            <code>null</code> if no process is associated with this debug
	 *            target (for example, a remote VM).
	 */
	protected void setProcess(IProcess process) {
		fProcess = process;
	}

	@Override
	public IProcess getProcess() {
		return fProcess;
	}

	/**
	 * Notification the underlying VM has died. Updates the state of this target
	 * to be terminated.
	 *
	 * @param event
	 *            VM death event
	 */
	public void handleVMDeath(VMDeathEvent event) {
		terminated();
	}

	/**
	 * Notification the underlying VM has disconnected. Updates the state of
	 * this target to be terminated.
	 *
	 * @param event
	 *            disconnect event
	 */
	public void handleVMDisconnect(VMDisconnectEvent event) {
		if (isTerminating()) {
			terminated();
		} else {
			disconnected();
		}
	}

	@Override
	public boolean isSuspended() {
		return fSuspended;
	}

	/**
	 * Sets whether this VM is suspended.
	 *
	 * @param suspended
	 *            whether this VM is suspended
	 */
	private void setSuspended(boolean suspended) {
		fSuspended = suspended;
	}

	/**
	 * Returns whether this target is available to handle VM requests
	 */
	public boolean isAvailable() {
		return !(isTerminated() || isTerminating() || isDisconnected() || isDisconnecting());
	}

	@Override
	public boolean isTerminated() {
		return fTerminated;
	}

	/**
	 * Sets whether this debug target is terminated
	 *
	 * @param terminated
	 *            <code>true</code> if this debug target is terminated,
	 *            otherwise <code>false</code>
	 */
	protected void setTerminated(boolean terminated) {
		fTerminated = terminated;
	}

	/**
	 * Sets whether this debug target is disconnected
	 *
	 * @param disconnected
	 *            <code>true</code> if this debug target is disconnected,
	 *            otherwise <code>false</code>
	 */
	protected void setDisconnected(boolean disconnected) {
		fDisconnected = disconnected;
	}

	@Override
	public boolean isDisconnected() {
		return fDisconnected;
	}

	/**
	 * Creates, enables and returns a class prepare request for the specified
	 * class name in this target.
	 *
	 * @param classPattern
	 *            regular expression specifying the pattern of class names that
	 *            will cause the event request to fire. Regular expressions may
	 *            begin with a '*', end with a '*', or be an exact match.
	 * @exception CoreException
	 *                if unable to create the request
	 */
	public ClassPrepareRequest createClassPrepareRequest(String classPattern)
			throws CoreException {
		return createClassPrepareRequest(classPattern, null);
	}

	/**
	 * Creates, enables and returns a class prepare request for the specified
	 * class name in this target. Can specify a class exclusion filter as well.
	 * This is a utility method used by event requesters that need to create
	 * class prepare requests.
	 *
	 * @param classPattern
	 *            regular expression specifying the pattern of class names that
	 *            will cause the event request to fire. Regular expressions may
	 *            begin with a '*', end with a '*', or be an exact match.
	 * @param classExclusionPattern
	 *            regular expression specifying the pattern of class names that
	 *            will not cause the event request to fire. Regular expressions
	 *            may begin with a '*', end with a '*', or be an exact match.
	 *            May be <code>null</code>.
	 * @exception CoreException
	 *                if unable to create the request
	 */
	public ClassPrepareRequest createClassPrepareRequest(String classPattern,
			String classExclusionPattern) throws CoreException {
		return createClassPrepareRequest(classPattern, classExclusionPattern,
				true);
	}

	/**
	 * Creates, enables and returns a class prepare request for the specified
	 * class name in this target. Can specify a class exclusion filter as well.
	 * This is a utility method used by event requesters that need to create
	 * class prepare requests.
	 *
	 * @param classPattern
	 *            regular expression specifying the pattern of class names that
	 *            will cause the event request to fire. Regular expressions may
	 *            begin with a '*', end with a '*', or be an exact match.
	 * @param classExclusionPattern
	 *            regular expression specifying the pattern of class names that
	 *            will not cause the event request to fire. Regular expressions
	 *            may begin with a '*', end with a '*', or be an exact match.
	 *            May be <code>null</code>.
	 * @param enabled
	 *            whether to enable the event request
	 * @exception CoreException
	 *                if unable to create the request
	 * @since 3.3
	 */
	public ClassPrepareRequest createClassPrepareRequest(String classPattern,
			String classExclusionPattern, boolean enabled) throws CoreException {
		return createClassPrepareRequest(classPattern, classExclusionPattern,
				enabled, null);
	}

	/**
	 * Creates, enables and returns a class prepare request for the specified
	 * class name in this target. Can specify a class exclusion filter as well.
	 * This is a utility method used by event requesters that need to create
	 * class prepare requests.
	 *
	 * @param classPattern
	 *            regular expression specifying the pattern of class names that
	 *            will cause the event request to fire. Regular expressions may
	 *            begin with a '*', end with a '*', or be an exact match. May be
	 *            <code>null</code> if sourceName is specified
	 * @param classExclusionPattern
	 *            regular expression specifying the pattern of class names that
	 *            will not cause the event request to fire. Regular expressions
	 *            may begin with a '*', end with a '*', or be an exact match.
	 *            May be <code>null</code>.
	 * @param enabled
	 *            whether to enable the event request
	 * @param sourceName
	 *            source name pattern to match or <code>null</code> if
	 *            classPattern is specified
	 * @exception CoreException
	 *                if unable to create the request
	 * @since 3.3
	 */
	public ClassPrepareRequest createClassPrepareRequest(String classPattern,
			String classExclusionPattern, boolean enabled, String sourceName)
			throws CoreException {
		EventRequestManager manager = getEventRequestManager();
		if (manager == null || !isAvailable()) {
			requestFailed(
					JDIDebugModelMessages.JDIDebugTarget_Unable_to_create_class_prepare_request___VM_disconnected__2,
					new VMDisconnectedException());
		}
		ClassPrepareRequest req = null;
		try {
			req = manager.createClassPrepareRequest();
			if (classPattern != null) {
				req.addClassFilter(classPattern);
			}
			if (classExclusionPattern != null) {
				req.addClassExclusionFilter(classExclusionPattern);
			}
			req.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
			if (sourceName != null) {
				req.addSourceNameFilter(sourceName);
			}
			if (enabled) {
				req.enable();
			}
		} catch (RuntimeException e) {
			targetRequestFailed(
					JDIDebugModelMessages.JDIDebugTarget_Unable_to_create_class_prepare_request__3,
					e);
			// execution will not reach here
			return null;
		}
		return req;
	}

	@Override
	public void resume() throws DebugException {
		// if a client calls resume, then we should resume on a VMStart event in
		// case
		// it has not yet been received, and the target was created with the
		// "resume"
		// flag as "false". See bug 32372.
		setResumeOnStartup(true);
		resume(true);
	}

	/**
	 * @see ISuspendResume#resume()
	 *
	 *      Updates the state of this debug target to resumed, but does not fire
	 *      notification of the resumption.
	 */
	public void resumeQuiet() throws DebugException {
		resume(false);
	}

	/**
	 * @see ISuspendResume#resume()
	 *
	 *      Updates the state of this debug target, but only fires notification
	 *      to listeners if <code>fireNotification</code> is <code>true</code>.
	 */
	protected void resume(boolean fireNotification) throws DebugException {
		if ((!isSuspended() && !canResumeThreads()) || !isAvailable()) {
			return;
		}
		try {
			setSuspended(false);
			resumeThreads();
			VirtualMachine vm = getVM();
			if (vm != null) {
				vm.resume();
			}
			if (fireNotification) {
				fireResumeEvent(DebugEvent.CLIENT_REQUEST);
			}
		} catch (VMDisconnectedException e) {
			disconnected();
			return;
		} catch (RuntimeException e) {
			setSuspended(true);
			fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
			targetRequestFailed(MessageFormat.format(
					JDIDebugModelMessages.JDIDebugTarget_exception_resume,
					e.toString()), e);
		}
	}

	@Override
	public boolean supportsBreakpoint(IBreakpoint breakpoint) {
		boolean isJava = breakpoint instanceof IJavaBreakpoint;
		if(!isJava){
			return false;
		}
		if(fScope == null){
			// No checks, everything in scope: the filtering is disabled
			return true;
		}

		IJavaBreakpoint jBreakpoint = (IJavaBreakpoint) breakpoint;

		// Check if the breakpoint from resources in target scope
		IMarker marker = jBreakpoint.getMarker();
		if(marker == null) {
			// Marker not available, so don't guess and allow the breakpoint to be set
			return true;
		}

		return supportsResource(() -> jBreakpoint.getTypeName(), marker.getResource());
	}


	public boolean supportsResource(Callable<String> typeNameSupplier, IResource resource) {
		if (fScope == null) {
			// No checks, everything in scope: the filtering is disabled
			return true;
		}
		// Java exception breakpoints have wsp root as resource
		if(resource == null || resource == ResourcesPlugin.getWorkspace().getRoot()) {
			return true;
		}
		Set<IProject> projects = fProjects;
		if(projects == null){
			return true;
		}

		// Breakpoint from project known by the resource mapping
		if (projects.contains(resource.getProject())) {
			return true;
		}

		// Check if this is a resource which is linked to any of the projects
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		URI uri = resource.getLocationURI();
		if(uri != null){
			IFile[] files = root.findFilesForLocationURI(uri);
			for (IFile file : files) {
				if(projects.contains(file.getProject())){
					return true;
				}
			}
		}

		Map<String, Boolean> knownTypes = fKnownTypes;
		if(knownTypes == null){
			return true;
		}

		// breakpoint belongs to resource outside of referenced projects?
		// This can be also an incomplete resource mapping.
		// Try to see if the type available multiple times in workspace
		try {
			String typeName = typeNameSupplier.call();
			if(typeName != null){
				Boolean known = knownTypes.get(typeName);
				if(known != null){
					return known.booleanValue();
				}
				boolean supportedBreakpoint = !hasMultipleMatchesInWorkspace(typeName);
				knownTypes.put(typeName, Boolean.valueOf(supportedBreakpoint));
				return supportedBreakpoint;
			}
		}
		catch (Exception e) {
			logError(e);
		}
		// we don't know why computation failed, so let assume the breakpoint is supported.
		return true;
	}

	private Set<IJavaProject> getJavaProjects(IResource... resources) {
		Set<IJavaProject> projects = new LinkedHashSet<>();
		for (IResource resource : resources) {
			IProject project = resource.getProject();
			if(!project.isAccessible()){
				continue;
			}
			IJavaElement javaElement = JavaCore.create(project);
			if(javaElement != null) {
				projects.add(javaElement.getJavaProject());
			}
		}
		return projects;
	}

	/**
	 * @param javaProjects the set which will be updated with all referenced java projects
	 * @return corresponding resource projects
	 */
	private Set<IProject> collectReferencedJavaProjects(Set<IJavaProject> javaProjects) {
		Set<IProject> projects = new LinkedHashSet<>();
		// collect all references
		for (IJavaProject jProject : javaProjects) {
			projects.add(jProject.getProject());
			addReferencedProjects(jProject, projects);
		}
		// update java projects set with new java projects we might collected
		for (IProject project : projects) {
			IJavaProject jProject = JavaCore.create(project);
			if(jProject != null){
				javaProjects.add(jProject);
			}
		}
		return projects;
	}

	private void addReferencedProjects(IJavaProject jProject, Set<IProject> projects) {
		IClasspathEntry[] cp;
		try {
			// we want resolved classpath to get variables and containers resolved for us
			cp = jProject.getResolvedClasspath(true);
		} catch (JavaModelException e) {
			// we don't care here
			return;
		}
		for (IClasspathEntry cpe : cp) {
			int entryKind = cpe.getEntryKind();
			IProject project = null;
			switch (entryKind) {
				case IClasspathEntry.CPE_LIBRARY:
					// we must check for external folders coming from other projects in the workspace
					project = getProjectOfExternalFolder(cpe);
					break;
				case IClasspathEntry.CPE_PROJECT:
					// we must add any projects referenced
					project = getProject(cpe);
					break;
				case IClasspathEntry.CPE_SOURCE:
					// we have the project already
				case IClasspathEntry.CPE_VARIABLE:
					// should not happen on resolved classpath
				case IClasspathEntry.CPE_CONTAINER:
					// should not happen on resolved classpath
				default:
					break;
			}

			if(project == null || projects.contains(project) || !project.isAccessible()){
				continue;
			}

			IJavaProject referenced = JavaCore.create(project);
			if (referenced != null) {
				// we have found new project, start recursion
				projects.add(project);
				addReferencedProjects(referenced, projects);
			}
		}
	}

	private IProject getProject(IClasspathEntry cpe) {
		IPath projectPath = cpe.getPath();
		if (projectPath == null || projectPath.isEmpty()) {
			return null;
		}
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IProject project = root.getProject(projectPath.lastSegment());
		if (project.isAccessible()) {
			return project;
		}
		return null;
	}

	private static IProject getProjectOfExternalFolder(IClasspathEntry cpe){
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		if(cpe.getContentKind() == IPackageFragmentRoot.K_BINARY){
			IPath path = cpe.getPath();
			if(path == null || path.isEmpty()){
				return null;
			}
			IProject project = root.getProject(path.segment(0));
			if(project.isAccessible()) {
				return project;
			}
		}
		return null;
	}

	/*
	 * Checks if the given type (computed from a breakpoint resource) exists multiple times in the workspace.
	 */
	private boolean hasMultipleMatchesInWorkspace(final String typeName) {
		final AtomicInteger matchCount = new AtomicInteger(0);
		String packageName = null;
		String simpleName = typeName;
		int lastDot = typeName.lastIndexOf('.');
		if(lastDot > 0 && lastDot < typeName.length() - 1){
			packageName = typeName.substring(0, lastDot);
			simpleName = typeName.substring(lastDot + 1);
		}
		// get rid of inner types, use outer type name
		final String fqName;
		int firstDoll = simpleName.indexOf('$');
		if(firstDoll > 0 && firstDoll < simpleName.length() - 1){
			simpleName = simpleName.substring(0, firstDoll);
			fqName = packageName + "." + simpleName; //$NON-NLS-1$
		} else {
			fqName = typeName;
		}

		final IProgressMonitor monitor = new NullProgressMonitor();
        TypeNameMatchRequestor requestor = new TypeNameMatchRequestor() {
			@Override
			public void acceptTypeNameMatch(TypeNameMatch match) {
				IType type = match.getType();
				if(fqName.equals(type.getFullyQualifiedName())){
					int count = matchCount.incrementAndGet();
					if(count > 1) {
						monitor.setCanceled(true);
					}
					return;
				}
			}
		};
		try {
			SearchEngine searchEngine = new SearchEngine();
			searchEngine.searchAllTypeNames(packageName != null? packageName.toCharArray() : null,
					SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
					simpleName.toCharArray(),
			        SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
			        IJavaSearchConstants.TYPE,
			        fScope,
			        requestor,
			        IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
			        monitor);
		} catch (JavaModelException e) {
			logError(e);
			return true;
		} catch (OperationCanceledException e){
			// expected if we cancelled the search on second match
		}
		return matchCount.get() > 1;
	}

	/**
	 * Notification a breakpoint has been added to the breakpoint manager. If
	 * the breakpoint is a Java breakpoint and this target is not terminated,
	 * the breakpoint is installed.
	 *
	 * @param breakpoint
	 *            the breakpoint added to the breakpoint manager
	 */
	@Override
	public void breakpointAdded(IBreakpoint breakpoint) {
		if (!isAvailable()) {
			return;
		}
		if (supportsBreakpoint(breakpoint)) {
			try {
				JavaBreakpoint javaBreakpoint = (JavaBreakpoint) breakpoint;
				if (!getBreakpoints().contains(breakpoint)) {
					if (!javaBreakpoint.shouldSkipBreakpoint()) {
						// If the breakpoint should be skipped, don't add the
						// breakpoint
						// request to the VM. Just add the breakpoint to the
						// collection so
						// we have it if the manager is later enabled.
						javaBreakpoint.addToTarget(this);
					}
					getBreakpoints().add(breakpoint);
				}
			} catch (CoreException e) {
				logError(e);
			}
		}
	}

	/**
	 * Notification that one or more attributes of the given breakpoint has
	 * changed. If the breakpoint is a Java breakpoint, the associated event
	 * request in the underlying VM is updated to reflect the new state of the
	 * breakpoint.
	 *
	 * @param breakpoint
	 *            the breakpoint that has changed
	 */
	@Override
	public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
	}

	/**
	 * Notification that the given breakpoint has been removed from the
	 * breakpoint manager. If this target is not terminated, the breakpoint is
	 * removed from the underlying VM.
	 *
	 * @param breakpoint
	 *            the breakpoint has been removed from the breakpoint manager.
	 */
	@Override
	public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
		if (!isAvailable()) {
			return;
		}
		if (supportsBreakpoint(breakpoint)) {
			try {
				((JavaBreakpoint) breakpoint).removeFromTarget(this);
				getBreakpoints().remove(breakpoint);
				Iterator<JDIThread> threads = getThreadIterator();
				while (threads.hasNext()) {
					threads.next()
							.removeCurrentBreakpoint(breakpoint);
				}
			} catch (CoreException e) {
				logError(e);
			}
		}
	}

	@Override
	public void suspend() throws DebugException {
		if (isSuspended()) {
			IThread[] threads = getThreads();
			for (IThread thread : threads) {
				((JDIThread) thread).suspend();
			}
			return;
		}
		try {
			VirtualMachine vm = getVM();
			prepareThreadsForClientSuspend();
			if (vm != null) {
				vm.suspend();
			}
			suspendThreads();
			setSuspended(true);
			fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
		} catch (RuntimeException e) {
			setSuspended(false);
			resumeThreads();
			fireResumeEvent(DebugEvent.CLIENT_REQUEST);
			targetRequestFailed(MessageFormat.format(
					JDIDebugModelMessages.JDIDebugTarget_exception_suspend,
					e.toString()), e);
		}

	}

	/**
	 * Prepares threads to suspend (terminates evaluations, waits for
	 * invocations, etc.).
	 *
	 * @exception DebugException
	 *                if a thread times out
	 */
	protected void prepareThreadsForClientSuspend() throws DebugException {
		Iterator<JDIThread> threads = getThreadIterator();
		while (threads.hasNext()) {
			threads.next().prepareForClientSuspend();
		}
	}

	/**
	 * Notifies threads that they have been suspended
	 */
	protected void suspendThreads() {
		Iterator<JDIThread> threads = getThreadIterator();
		while (threads.hasNext()) {
			threads.next().suspendedByVM();
		}
	}

	/**
	 * Notifies threads that they have been resumed
	 */
	protected void resumeThreads() throws DebugException {
		Iterator<JDIThread> threads = getThreadIterator();
		while (threads.hasNext()) {
			threads.next().resumedByVM();
		}
	}

	/**
	 * Notifies this VM to update its state in preparation for a suspend.
	 *
	 * @param breakpoint
	 *            the breakpoint that caused the suspension
	 */
	public void prepareToSuspendByBreakpoint(JavaBreakpoint breakpoint) {
		setSuspended(true);
		suspendThreads();
	}

	/**
	 * Notifies this VM it has been suspended by the given breakpoint
	 *
	 * @param breakpoint
	 *            the breakpoint that caused the suspension
	 */
	protected void suspendedByBreakpoint(JavaBreakpoint breakpoint,
			boolean queueEvent, EventSet set) {
		if (queueEvent) {
			queueSuspendEvent(DebugEvent.BREAKPOINT, set);
		} else {
			fireSuspendEvent(DebugEvent.BREAKPOINT);
		}
	}

	/**
	 * Notifies this VM suspension has been cancelled
	 *
	 * @param breakpoint
	 *            the breakpoint that caused the suspension
	 */
	protected void cancelSuspendByBreakpoint(JavaBreakpoint breakpoint)
			throws DebugException {
		setSuspended(false);
		resumeThreads();
	}

	@Override
	public void terminate() throws DebugException {
		if (!isAvailable()) {
			return;
		}
		if (!supportsTerminate()) {
			notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_termination);
		}
		try {
			setTerminating(true);
			disposeThreadHandlers();
			VirtualMachine vm = getVM();
			if (vm != null) {
				vm.exit(1);
			}
			IProcess process = getProcess();
			if (process != null) {
				process.terminate();
			}
		} catch (VMDisconnectedException e) {
			// if the VM disconnects while exiting, perform
			// normal termination processing
			terminated();
		} catch (TimeoutException exception) {
			// if there is a timeout see if the associated process is terminated
			IProcess process = getProcess();
			if (process != null && process.isTerminated()) {
				terminated();
			} else {
				// All we can do is disconnect
				disconnected();
			}
		} catch (RuntimeException e) {
			targetRequestFailed(MessageFormat.format(
					JDIDebugModelMessages.JDIDebugTarget_exception_terminating,
					e.toString()), e);
		}
	}

	/**
	 * Updates the state of this target to be terminated, if not already
	 * terminated.
	 */
	protected void terminated() {
		setTerminating(false);
		if (!isTerminated()) {
			setTerminated(true);
			setDisconnected(true);
			cleanup();
			fireTerminateEvent();
		}
	}

	/**
	 * Updates the state of this target for disconnection from the VM.
	 */
	@Override
	protected void disconnected() {
		setDisconnecting(false);
		if (!isDisconnected()) {
			setDisconnected(true);
			cleanup();
			fireTerminateEvent();
		}
	}

	/**
	 * Cleans up the internal state of this debug target as a result of a
	 * session ending with a VM (as a result of a disconnect or termination of
	 * the VM).
	 * <p>
	 * All threads are removed from this target. This target is removed as a
	 * breakpoint listener, and all breakpoints are removed from this target.
	 * </p>
	 */
	protected void cleanup() {
		removeAllThreads();
		DebugPlugin plugin = DebugPlugin.getDefault();
		plugin.getBreakpointManager().removeBreakpointListener(this);
		plugin.getLaunchManager().removeLaunchListener(this);
		plugin.getBreakpointManager().removeBreakpointManagerListener(this);
		plugin.removeDebugEventListener(this);
		removeAllBreakpoints();
		DebugPlugin.getDefault().getBreakpointManager().enableTriggerPoints(null, true);
		fOutOfSynchTypes.clear();
		if (fEngines != null) {
			Iterator<IAstEvaluationEngine> engines = fEngines.values().iterator();
			while (engines.hasNext()) {
				IAstEvaluationEngine engine = engines
						.next();
				engine.dispose();
			}
			fEngines.clear();
		}
		fVirtualMachine = null;
		setThreadStartHandler(null);
		setEventDispatcher(null);
		setStepFilters(new String[0]);
		fHCRListeners.clear();
		fKnownTypes = null;
		fProjects = null;
		fScope = null;
	}

	/**
	 * Removes all threads from this target's collection of threads, firing a
	 * terminate event for each.
	 */
	protected void removeAllThreads() {
		Iterator<JDIThread> itr = getThreadIterator();
		while (itr.hasNext()) {
			JDIThread child = itr.next();
			child.terminated();
		}
		synchronized (fThreads) {
			fThreads.clear();
		}
	}

	/**
	 * Removes all breakpoints from this target, such that each breakpoint can
	 * update its install count. This target's collection of breakpoints is
	 * cleared.
	 */
	protected void removeAllBreakpoints() {
		List<IBreakpoint> list = new ArrayList<>(getBreakpoints());
		for(IBreakpoint bp : list) {
			JavaBreakpoint breakpoint = (JavaBreakpoint) bp;
			try {
				breakpoint.removeFromTarget(this);
			} catch (CoreException e) {
				logError(e);
			}
		}
		getBreakpoints().clear();
	}

	/**
	 * Adds all the breakpoints in this target's collection to this debug
	 * target.
	 */
	protected void reinstallAllBreakpoints() {
		List<IBreakpoint> list = new ArrayList<>(getBreakpoints());
		for(IBreakpoint bp : list) {
			JavaBreakpoint breakpoint = (JavaBreakpoint) bp;
			try {
				breakpoint.addToTarget(this);
			} catch (CoreException e) {
				logError(e);
			}
		}
	}

	/**
	 * Returns VirtualMachine.classesByName(String), logging any JDI exceptions.
	 *
	 * @see com.sun.jdi.VirtualMachine
	 */
	public List<ReferenceType> jdiClassesByName(String className) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			try {
				return vm.classesByName(className);
			} catch (VMDisconnectedException e) {
				if (!isAvailable()) {
					return Collections.EMPTY_LIST;
				}
				logError(e);
			} catch (RuntimeException e) {
				internalError(e);
			}
		}
		return Collections.EMPTY_LIST;
	}

	@Override
	public IJavaVariable findVariable(String varName) throws DebugException {
		IThread[] threads = getThreads();
		for (IThread thread2 : threads) {
			IJavaThread thread = (IJavaThread) thread2;
			IJavaVariable var = thread.findVariable(varName);
			if (var != null) {
				return var;
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getAdapter(Class<T> adapter) {
		if (adapter == IJavaDebugTarget.class) {
			return (T) this;
		}
		return super.getAdapter(adapter);
	}

	/**
	 * The JDIDebugPlugin is shutting down. Shutdown the event dispatcher and do
	 * local cleanup.
	 */
	public void shutdown() {
		EventDispatcher dispatcher = ((JDIDebugTarget) getDebugTarget())
				.getEventDispatcher();
		if (dispatcher != null) {
			dispatcher.shutdown();
		}
		try {
			if (supportsTerminate()) {
				terminate();
			} else if (supportsDisconnect()) {
				disconnect();
			}
		} catch (DebugException e) {
			JDIDebugPlugin.log(e);
		}
		cleanup();
	}

	/**
	 * Returns the CRC-32 of the entire class file contents associated with
	 * given type, on the target VM, or <code>null</code> if the type is not
	 * loaded, or a CRC for the type is not known.
	 *
	 * @param typeName
	 *            fully qualified name of the type for which a CRC is required.
	 *            For example, "com.example.Example".
	 * @return 32 bit CRC, or <code>null</code>
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                </ul>
	 */
	protected Integer getCRC(String typeName) throws DebugException {
		if (getVM() instanceof org.eclipse.jdi.hcr.VirtualMachine) {
			List<ReferenceType> classes = jdiClassesByName(typeName);
			if (!classes.isEmpty()) {
				ReferenceType type = classes.get(0);
				if (type instanceof org.eclipse.jdi.hcr.ReferenceType) {
					try {
						org.eclipse.jdi.hcr.ReferenceType rt = (org.eclipse.jdi.hcr.ReferenceType) type;
						if (rt.isVersionKnown()) {
							return Integer.valueOf(rt.getClassFileVersion());
						}
					} catch (RuntimeException e) {
						targetRequestFailed(
								MessageFormat.format(
										JDIDebugModelMessages.JDIDebugTarget_exception_retrieving_version_information,
										e.toString(), type.name()), e);
						// execution will never reach this line, as
						// #targetRequestFailed will throw an exception
						return null;
					}
				}
			}
		}
		return null;
	}

	@Override
	public IJavaType[] getJavaTypes(String name) throws DebugException {
		try {
			// get java.lang.Class
			VirtualMachine vm = getVM();
			if (vm == null) {
				requestFailed(
						JDIDebugModelMessages.JDIDebugTarget_Unable_to_retrieve_types___VM_disconnected__4,
						new VMDisconnectedException());
			}
			List<ReferenceType> classes = vm.classesByName(name);
			if (classes.isEmpty()) {
				switch (name.charAt(0)) {
				case 'b':
					if (name.equals("boolean")) { //$NON-NLS-1$
						return new IJavaType[] { newValue(true).getJavaType() };
					} else if (name.equals("byte")) { //$NON-NLS-1$
						return new IJavaType[] { newValue((byte) 1)
								.getJavaType() };
					}
					break;
				case 'i':
					if (name.equals("int")) { //$NON-NLS-1$
						return new IJavaType[] { newValue(1).getJavaType() };
					}
					break;
				case 'l':
					if (name.equals("long")) { //$NON-NLS-1$
						return new IJavaType[] { newValue(1l).getJavaType() };
					}
					break;
				case 'c':
					if (name.equals("char")) { //$NON-NLS-1$
						return new IJavaType[] { newValue(' ').getJavaType() };
					}
					break;
				case 's':
					if (name.equals("short")) { //$NON-NLS-1$
						return new IJavaType[] { newValue((short) 1)
								.getJavaType() };
					}
					break;
				case 'f':
					if (name.equals("float")) { //$NON-NLS-1$
						return new IJavaType[] { newValue(1f).getJavaType() };
					}
					break;
				case 'd':
					if (name.equals("double")) { //$NON-NLS-1$
						return new IJavaType[] { newValue(1d).getJavaType() };
					}
					break;
				}
				return null;
			}
			IJavaType[] types = new IJavaType[classes.size()];
			for (int i = 0; i < types.length; i++) {
				types[i] = JDIType.createType(this, classes.get(i));
			}
			return types;
		} catch (RuntimeException e) {
			targetRequestFailed(
					MessageFormat
							.format("{0} occurred while retrieving class for name {1}", e.toString(), name), e); //$NON-NLS-1$
			// execution will not reach this line, as
			// #targetRequestFailed will throw an exception
			return null;
		}
	}

	@Override
	public IJavaValue newValue(boolean value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(byte value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(char value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(double value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(float value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(int value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(long value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(short value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue newValue(String value) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			Value v = vm.mirrorOf(value);
			return JDIValue.createValue(this, v);
		}
		return null;
	}

	@Override
	public IJavaValue nullValue() {
		return JDIValue.createValue(this, null);
	}

	@Override
	public IJavaValue voidValue() {
		return new JDIVoidValue(this);
	}

	protected boolean isTerminating() {
		return fTerminating;
	}

	protected void setTerminating(boolean terminating) {
		fTerminating = terminating;
	}

	protected boolean isDisconnecting() {
		return fDisconnecting;
	}

	protected void setDisconnecting(boolean disconnecting) {
		fDisconnecting = disconnecting;
	}

	/**
	 * An event handler for thread start events. When a thread starts in the
	 * target VM, a model thread is created.
	 */
	class ThreadStartHandler implements IJDIEventListener {

		protected EventRequest fRequest;

		protected ThreadStartHandler() {
			createRequest();
		}

		/**
		 * Creates and registers a request to handle all thread start events
		 */
		protected void createRequest() {
			EventRequestManager manager = getEventRequestManager();
			if (manager != null) {
				try {
					EventRequest req = manager.createThreadStartRequest();
					req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
					req.enable();
					addJDIEventListener(this, req);
					setRequest(req);
				} catch (RuntimeException e) {
					logError(e);
				}
			}
		}

		/**
		 * Creates a model thread for the underlying JDI thread and adds it to
		 * the collection of threads for this debug target. As a side effect of
		 * creating the thread, a create event is fired for the model thread.
		 * The event is ignored if the underlying thread is already marked as
		 * collected.
		 *
		 * @param event
		 *            a thread start event
		 * @param target
		 *            the target in which the thread started
		 * @return <code>true</code> - the thread should be resumed
		 */
		@Override
		public boolean handleEvent(Event event, JDIDebugTarget target,
				boolean suspendVote, EventSet eventSet) {
			ThreadReference thread = ((ThreadStartEvent) event).thread();
			try {
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=443727
				// the backing ThreadReference could be read in as null
				if (thread == null || thread.isCollected()) {
					return false;
				}
			} catch (VMDisconnectedException exception) {
				return false;
			} catch (ObjectCollectedException e) {
				return false;
			} catch (TimeoutException e) {
				// continue - attempt to create the thread
			}
			JDIThread jdiThread = findThread(thread);
			if (jdiThread == null) {
				jdiThread = createThread(thread);
				if (jdiThread == null) {
					return false;
				}
			} else {
				jdiThread.disposeStackFrames();
				jdiThread.fireChangeEvent(DebugEvent.CONTENT);
			}
			return !jdiThread.isSuspended();
		}

		@Override
		public void eventSetComplete(Event event, JDIDebugTarget target,
				boolean suspend, EventSet eventSet) {
			// do nothing
		}

		/**
		 * unregisters this event listener.
		 */
		protected void deleteRequest() {
			if (getRequest() != null) {
				removeJDIEventListener(this, getRequest());
				setRequest(null);
			}
		}

		protected EventRequest getRequest() {
			return fRequest;
		}

		protected void setRequest(EventRequest request) {
			fRequest = request;
		}
	}

	/**
	 * An event handler for thread death events. When a thread dies in the
	 * target VM, its associated model thread is removed from the debug target.
	 */
	class ThreadDeathHandler implements IJDIEventListener {

		// terminated threads marked for removal from the fThreads list
		private Map<Event, JDIThread> toRemove = Collections.synchronizedMap(new HashMap<>());

		protected ThreadDeathHandler() {
			createRequest();
		}

		/**
		 * Creates and registers a request to listen to thread death events.
		 */
		protected void createRequest() {
			EventRequestManager manager = getEventRequestManager();
			if (manager != null) {
				try {
					EventRequest req = manager.createThreadDeathRequest();
					req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
					req.enable();
					addJDIEventListener(this, req);
				} catch (RuntimeException e) {
					logError(e);
				}
			}
		}

		/**
		 * Locates the model thread associated with the underlying JDI thread that has terminated, and marks it for removal from the collection of
		 * threads belonging to this debug target. A terminate event is fired for the model thread.
		 *
		 * @param event
		 *            a thread death event
		 * @param target
		 *            the target in which the thread died
		 * @return <code>true</code> - the thread should be resumed
		 */
		@Override
		public boolean handleEvent(Event event, JDIDebugTarget target,
				boolean suspend, EventSet eventSet) {
			ThreadReference ref = ((ThreadDeathEvent) event).thread();
			JDIThread thread = findThread(ref);
			if (thread == null) {
				thread = target.findThread(ref);
			}
			if (thread != null) {
				toRemove.put(event, thread);
				// triggers DebugEvent
				thread.terminated();
			}
			return true;
		}

		/**
		 * Removes the model thread associated with the underlying JDI thread that has terminated from the collection of threads belonging to this
		 * debug target.
		 *
		 * @param event
		 *            a thread death event
		 * @param target
		 *            the target in which the thread died
		 */
		@Override
		public void eventSetComplete(Event event, JDIDebugTarget target, boolean suspendVote, EventSet eventSet) {
			JDIThread thread = toRemove.remove(event);
			if (thread != null) {
				synchronized (fThreads) {
					fThreads.remove(thread);
				}
			}
		}

	}

	/**
	 * Triggers updates on a thread when {@link java.lang.Thread#setName(String)} is called on that thread, in the target JVM.
	 */
	class ThreadNameChangeHandler implements IJDIEventListener {

		/**
		 * Environment variable that can be passed down to Eclipse, to disable this listener.
		 */
		private static final String DISABLE_THREAD_NAME_CHANGE_LISTENER = "org.eclipse.jdt.internal.debug.core.model.ThreadNameChangeListener.disable"; //$NON-NLS-1$
		private static final String TYPE_NAME = "java.lang.Thread"; //$NON-NLS-1$
		private static final String METHOD_NAME = "setName"; //$NON-NLS-1$
		private static final String METHOD_SIGNATURE = "(Ljava/lang/String;)V"; //$NON-NLS-1$

		private EventRequest request;
		private ThreadChangeNotifierJob notfierJob;

		ThreadNameChangeHandler() {
			String disableListenerSystemProperty = System.getProperty(DISABLE_THREAD_NAME_CHANGE_LISTENER);
			boolean isDisabled = String.valueOf(Boolean.TRUE).equals(disableListenerSystemProperty);
			if (!isDisabled) {
				createRequest();
				notfierJob = new ThreadChangeNotifierJob();
			}
		}

		/**
		 * Creates a breakpoint request at {@link java.lang.Thread#setName(String)} that doesn't suspend the target JVM.
		 */
		void createRequest() {
			EventRequestManager manager = getEventRequestManager();
			if (manager != null) {
				try {
					Location location = locationOfSetNameMethod();
					if (location != null) {
						request = manager.createBreakpointRequest(location);
						request.setSuspendPolicy(EventRequest.SUSPEND_NONE);
						request.enable();
						addJDIEventListener(this, request);
					}
				} catch (RuntimeException e) {
					String errorMessage = "Failed to add thread name change listener to debug target " + JDIDebugTarget.this; //$NON-NLS-1$
					IStatus errorStatus = new Status(IStatus.ERROR, JDIDebugPlugin.getUniqueIdentifier(), errorMessage, e);
					logRequestStatus(errorStatus);
				}
			}
		}

		private Location locationOfSetNameMethod() {
			List<ReferenceType> types = jdiClassesByName(TYPE_NAME);
			boolean foundThreadType = false;
			for (ReferenceType type : types) {
				if (type instanceof ClassType) {
					foundThreadType = true;
					Method method = ((ClassType) type).concreteMethodByName(METHOD_NAME, METHOD_SIGNATURE);
					if (method != null && !method.isNative()) {
						Location location = method.location();
						if (location != null && location.codeIndex() != -1) {
							return location;
						}
						logRequestWarning("Unable to find location of java.lang.Thread.setName() in debuggee JVM, for type " + type); //$NON-NLS-1$
					} else {
						logRequestWarning("Unable to find java.lang.Thread.setName() method in debuggee JVM, for type " + type); //$NON-NLS-1$
					}
				}
			}
			if (!foundThreadType) {
				logRequestWarning("Unable to find type java.lang.Thread.setName() in debuggee JVM"); //$NON-NLS-1$
			}
			return null;
		}

		void deleteRequest() {
			if (request != null) {
				removeJDIEventListener(this, request);
			}
			if (notfierJob != null) {
				notfierJob.stop();
			}
		}

		@Override
		public boolean handleEvent(Event event, JDIDebugTarget target, boolean suspend, EventSet eventSet) {
			ThreadReference ref = ((LocatableEvent) event).thread();
			JDIThread thread = findThread(ref);
			if (thread == null) {
				thread = target.findThread(ref);
			}
			if (thread != null) {
				// trigger updates on the thread
				notfierJob.notifyAboutChange(thread);
			}
			// we never suspend the thread
			return true;
		}

		@Override
		public void eventSetComplete(Event event, JDIDebugTarget target, boolean suspendVote, EventSet eventSet) {
			// nothing to do here, we do work in handleEvent
		}

		private void logRequestWarning(String warningMessage) {
			IStatus warningStatus = new Status(IStatus.WARNING, JDIDebugPlugin.getUniqueIdentifier(), warningMessage);
			logRequestStatus(warningStatus);
		}

		private void logRequestStatus(IStatus status) {
			if (isAvailable()) {
				JDIDebugPlugin.log(status);
			}
		}
	}

	/**
	 * Job to throttle thread name change events notification.
	 */
	class ThreadChangeNotifierJob extends Job {

		private final LinkedHashSet<JDIThread> queue;

		public ThreadChangeNotifierJob() {
			super(JDIDebugModelMessages.JDIDebugTarget_ThreadNameNotifier);
			setSystem(true);
			setPriority(Job.DECORATE);
			queue = new LinkedHashSet<>();
		}

		public void notifyAboutChange(JDIThread thread) {
			synchronized (queue) {
				if (queue.add(thread)) {
					// if there are too many threads changing names, they may slow down debugger
					int delay = Math.min(1000, 300 * queue.size());
					schedule(delay);
				}
			}
		}

		void stop() {
			synchronized (queue) {
				queue.clear();
			}
			cancel();
		}

		@Override
		protected IStatus run(IProgressMonitor monitor) {
			DebugEvent[] events;
			synchronized (queue) {
				events = queue.stream().map(t -> new DebugEvent(t, DebugEvent.CHANGE, DebugEvent.STATE)).toArray(DebugEvent[]::new);
				queue.clear();
			}
			if (monitor.isCanceled()) {
				return Status.CANCEL_STATUS;
			}
			// Dispatch known events
			DebugPlugin.getDefault().fireDebugEventSet(events);
			return Status.OK_STATUS;
		}


		@Override
		public boolean belongsTo(Object family) {
			return family == JDIDebugTarget.this;
		}
	}

	class CleanUpJob extends Job {

		/**
		 * Constructs a job to cleanup a hanging target.
		 */
		public CleanUpJob() {
			super(JDIDebugModelMessages.JDIDebugTarget_0);
			setSystem(true);
		}

		@Override
		protected IStatus run(IProgressMonitor monitor) {
			if (isAvailable()) {
				if (fEventDispatcher != null) {
					fEventDispatcher.shutdown();
				}
				disconnected();
			}
			return Status.OK_STATUS;
		}

		@Override
		public boolean shouldRun() {
			return isAvailable();
		}

		@Override
		public boolean shouldSchedule() {
			return isAvailable();
		}

	}

	protected ThreadStartHandler getThreadStartHandler() {
		return fThreadStartHandler;
	}

	protected void setThreadStartHandler(ThreadStartHandler threadStartHandler) {
		fThreadStartHandler = threadStartHandler;
	}

	private ThreadNameChangeHandler getThreadNameChangeHandler() {
		return fThreadNameChangeHandler;
	}

	private void setThreadNameChangeHandler(ThreadNameChangeHandler threadNameChangeHandler) {
		fThreadNameChangeHandler = threadNameChangeHandler;
	}

	/**
	 * Java debug targets do not support storage retrieval.
	 *
	 * @see IMemoryBlockRetrieval#supportsStorageRetrieval()
	 */
	@Override
	public boolean supportsStorageRetrieval() {
		return false;
	}

	@Override
	public IMemoryBlock getMemoryBlock(long startAddress, long length)
			throws DebugException {
		notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_storage_retrieval);
		// this line will not be executed as #notSupported(String)
		// will throw an exception
		return null;
	}

	@Override
	public void launchRemoved(ILaunch launch) {
		if (!isAvailable()) {
			return;
		}
		if (launch.equals(getLaunch())) {
			// This target has been unregistered, but it hasn't successfully
			// terminated.
			// Update internal state to reflect that it is disconnected
			disconnected();
		}
	}

	@Override
	public void launchAdded(ILaunch launch) {
	}

	@Override
	public void launchChanged(ILaunch launch) {
	}

	/**
	 * Sets whether the VM should be resumed on startup. Has no effect if the VM
	 * is already running when this target is created.
	 *
	 * @param resume
	 *            whether the VM should be resumed on startup
	 */
	private synchronized void setResumeOnStartup(boolean resume) {
		fResumeOnStartup = resume;
	}

	/**
	 * Returns whether this VM should be resumed on startup.
	 *
	 * @return whether this VM should be resumed on startup
	 */
	protected synchronized boolean isResumeOnStartup() {
		return fResumeOnStartup;
	}

	@Override
	public String[] getStepFilters() {
		return fStepFilters;
	}

	@Override
	public boolean isFilterConstructors() {
		return (fStepFilterMask & FILTER_CONSTRUCTORS) > 0;
	}

	@Override
	public boolean isFilterStaticInitializers() {
		return (fStepFilterMask & FILTER_STATIC_INITIALIZERS) > 0;
	}

	@Override
	public boolean isFilterSynthetics() {
		return (fStepFilterMask & FILTER_SYNTHETICS) > 0;
	}

	/*
	 * (non-Javadoc) Was added in 3.3, made API in 3.5
	 */
	@Override
	public boolean isStepThruFilters() {
		return (fStepFilterMask & STEP_THRU_FILTERS) > 0;
	}

	@Override
	public boolean isStepFiltersEnabled() {
		return (fStepFilterMask & STEP_FILTERS_ENABLED) > 0;
	}

	@Override
	public void setFilterConstructors(boolean filter) {
		if (filter) {
			fStepFilterMask = fStepFilterMask | FILTER_CONSTRUCTORS;
		} else {
			fStepFilterMask = fStepFilterMask
					& (FILTER_CONSTRUCTORS ^ XOR_MASK);
		}
	}

	@Override
	public void setFilterStaticInitializers(boolean filter) {
		if (filter) {
			fStepFilterMask = fStepFilterMask | FILTER_STATIC_INITIALIZERS;
		} else {
			fStepFilterMask = fStepFilterMask
					& (FILTER_STATIC_INITIALIZERS ^ XOR_MASK);
		}
	}

	@Override
	public void setFilterSynthetics(boolean filter) {
		if (filter) {
			fStepFilterMask = fStepFilterMask | FILTER_SYNTHETICS;
		} else {
			fStepFilterMask = fStepFilterMask & (FILTER_SYNTHETICS ^ XOR_MASK);
		}
	}

	/*
	 * (non-Javadoc) Was added in 3.3, made API in 3.5
	 */
	@Override
	public void setStepThruFilters(boolean thru) {
		if (thru) {
			fStepFilterMask = fStepFilterMask | STEP_THRU_FILTERS;
		} else {
			fStepFilterMask = fStepFilterMask & (STEP_THRU_FILTERS ^ XOR_MASK);
		}
	}

	@Override
	public boolean isFilterGetters() {
		return (fStepFilterMask & FILTER_GETTERS) > 0;
	}

	@Override
	public void setFilterGetters(boolean filter) {
		if (filter) {
			fStepFilterMask = fStepFilterMask | FILTER_GETTERS;
		} else {
			fStepFilterMask = fStepFilterMask & (FILTER_GETTERS ^ XOR_MASK);
		}
	}

	@Override
	public boolean isFilterSetters() {
		return (fStepFilterMask & FILTER_SETTERS) > 0;
	}

	@Override
	public void setFilterSetters(boolean filter) {
		if (filter) {
			fStepFilterMask = fStepFilterMask | FILTER_SETTERS;
		} else {
			fStepFilterMask = fStepFilterMask & (FILTER_SETTERS ^ XOR_MASK);
		}
	}

	@Override
	public void setStepFilters(String[] list) {
		fStepFilters = list;
	}

	@Override
	public void setStepFiltersEnabled(boolean enabled) {
		if (enabled) {
			fStepFilterMask = fStepFilterMask | STEP_FILTERS_ENABLED;
		} else {
			fStepFilterMask = fStepFilterMask
					& (STEP_FILTERS_ENABLED ^ XOR_MASK);
		}
	}

	@Override
	public boolean hasThreads() {
		return fThreads.size() > 0;
	}

	@Override
	public ILaunch getLaunch() {
		return fLaunch;
	}

	/**
	 * Sets the launch this target is contained in
	 *
	 * @param launch
	 *            the launch this target is contained in
	 */
	private void setLaunch(ILaunch launch) {
		fLaunch = launch;
	}

	/**
	 * Returns the number of suspend events that have occurred in this target.
	 *
	 * @return the number of suspend events that have occurred in this target
	 */
	protected int getSuspendCount() {
		return fSuspendCount;
	}

	/**
	 * Increments the suspend counter for this target based on the reason for
	 * the suspend event. The suspend count is not updated for implicit
	 * evaluations.
	 *
	 * @param eventDetail
	 *            the reason for the suspend event
	 */
	protected void incrementSuspendCount(int eventDetail) {
		if (eventDetail != DebugEvent.EVALUATION_IMPLICIT) {
			fSuspendCount++;
		}
	}

	/**
	 * Returns an evaluation engine for the given project, creating one if
	 * necessary.
	 *
	 * @param project
	 *            java project
	 * @return evaluation engine
	 */
	public IAstEvaluationEngine getEvaluationEngine(IJavaProject project) {
		if (fEngines == null) {
			fEngines = new HashMap<>(2);
		}
		IAstEvaluationEngine engine = fEngines
				.get(project);
		if (engine == null) {
			engine = EvaluationManager.newAstEvaluationEngine(project, this);
			fEngines.put(project, engine);
		}
		return engine;
	}

	@Override
	public boolean supportsMonitorInformation() {
		if (!isAvailable()) {
			return false;
		}
		VirtualMachine vm = getVM();
		if (vm != null) {
			return vm.canGetCurrentContendedMonitor() && vm.canGetMonitorInfo()
					&& vm.canGetOwnedMonitorInfo();
		}
		return false;
	}

	/**
	 * Sets whether or not this debug target is currently performing a hot code
	 * replace.
	 */
	public void setIsPerformingHotCodeReplace(boolean isPerformingHotCodeReplace) {
		fIsPerformingHotCodeReplace = isPerformingHotCodeReplace;
	}

	@Override
	public boolean isPerformingHotCodeReplace() {
		return fIsPerformingHotCodeReplace;
	}

	@Override
	public boolean supportsAccessWatchpoints() {
		VirtualMachine vm = getVM();
		if (isAvailable() && vm != null) {
			return vm.canWatchFieldAccess();
		}
		return false;
	}

	@Override
	public boolean supportsModificationWatchpoints() {
		VirtualMachine vm = getVM();
		if (isAvailable() && vm != null) {
			return vm.canWatchFieldModification();
		}
		return false;
	}

	@Override
	public void setDefaultStratum(String stratum) {
		VirtualMachine vm = getVM();
		if (vm != null) {
			vm.setDefaultStratum(stratum);
		}
	}

	@Override
	public String getDefaultStratum() {
		VirtualMachine vm = getVM();
		if (vm != null) {
			return vm.getDefaultStratum();
		}
		return null;
	}

	@Override
	public boolean supportsStepFilters() {
		return isAvailable();
	}

	/**
	 * When the breakpoint manager disables, remove all registered breakpoints
	 * requests from the VM. When it enables, reinstall them.
	 */
	@Override
	public void breakpointManagerEnablementChanged(boolean enabled) {
		if (!isAvailable()) {
			return;
		}
		List<IBreakpoint> list = new ArrayList<>(getBreakpoints());
		for(IBreakpoint bp : list) {
			JavaBreakpoint breakpoint = (JavaBreakpoint) bp;
			try {
				if (enabled) {
					breakpoint.addToTarget(this);
				} else if (breakpoint.shouldSkipBreakpoint()) {
					breakpoint.removeFromTarget(this);
				}
			} catch (CoreException e) {
				logError(e);
			}
		}
	}

	@Override
	public void handleDebugEvents(DebugEvent[] events) {
		if (events.length == 1) {
			DebugEvent event = events[0];
			if (event.getSource().equals(getProcess())
					&& event.getKind() == DebugEvent.TERMINATE) {
				// schedule a job to clean up the target in case we never get a
				// terminate/disconnect
				// event from the VM
				int timeout = getRequestTimeout();
				if (timeout < 0) {
					timeout = 3000;
				}
				new CleanUpJob().schedule(timeout);
			}
		}
	}

	@Override
	public IDebugTarget getDebugTarget() {
		return this;
	}

	/**
	 * Adds the given thread group to the list of known thread groups. Also adds
	 * any parent thread groups that have not already been added to the list.
	 *
	 * @param group
	 *            thread group to add
	 */
	void addThreadGroup(ThreadGroupReference group) {
		ThreadGroupReference currentGroup = group;
		while (currentGroup != null) {
			synchronized (fGroups) {
				if (findThreadGroup(currentGroup) == null) {
					JDIThreadGroup modelGroup = new JDIThreadGroup(this,
							currentGroup);
					fGroups.add(modelGroup);
					currentGroup = currentGroup.parent();
				} else {
					currentGroup = null;
				}
			}
		}
	}

	JDIThreadGroup findThreadGroup(ThreadGroupReference group) {
		synchronized (fGroups) {
			Iterator<JDIThreadGroup> groups = fGroups.iterator();
			while (groups.hasNext()) {
				JDIThreadGroup modelGroup = groups.next();
				if (modelGroup.getUnderlyingThreadGroup().equals(group)) {
					return modelGroup;
				}
			}
		}
		return null;
	}

	@Override
	public IJavaThreadGroup[] getRootThreadGroups() throws DebugException {
		try {
			VirtualMachine vm = getVM();
			if (vm == null) {
				return new IJavaThreadGroup[0];
			}
			List<ThreadGroupReference> groups = vm.topLevelThreadGroups();
			List<JDIThreadGroup> modelGroups = new ArrayList<>(groups.size());
			for(ThreadGroupReference ref : groups) {
				JDIThreadGroup group = findThreadGroup(ref);
				if (group != null) {
					modelGroups.add(group);
				}
			}
			return modelGroups.toArray(new IJavaThreadGroup[modelGroups.size()]);
		} catch (VMDisconnectedException e) {
			// if the VM has disconnected, there are no thread groups
			return new IJavaThreadGroup[0];
		} catch (RuntimeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIDebugTarget_1, e);
		}
		return null;
	}

	@Override
	public IJavaThreadGroup[] getAllThreadGroups() throws DebugException {
		synchronized (fGroups) {
			return fGroups
					.toArray(new IJavaThreadGroup[fGroups.size()]);
		}
	}

	@Override
	public boolean supportsInstanceRetrieval() {
		VirtualMachine vm = getVM();
		if (vm != null) {
			return vm.canGetInstanceInfo();
		}
		return false;
	}

	/**
	 * Sends a JDWP command to the back end and returns the JDWP reply packet as
	 * bytes. This method creates an appropriate command header and packet id,
	 * before sending to the back end.
	 *
	 * @param commandSet
	 *            command set identifier as defined by JDWP
	 * @param commandId
	 *            command identifier as defined by JDWP
	 * @param data
	 *            any bytes required for the command that follow the command
	 *            header or <code>null</code> for commands that have no data
	 * @return raw reply packet as bytes defined by JDWP
	 * @exception IOException
	 *                if an error occurs sending the packet or receiving the
	 *                reply
	 * @since 3.3
	 */
	public byte[] sendJDWPCommand(byte commandSet, byte commandId, byte[] data)
			throws IOException {
		int command = (256 * commandSet) + commandId;
		JdwpReplyPacket reply = ((VirtualMachineImpl) getVM()).requestVM(
				command, data);
		return reply.getPacketAsBytes();
	}

	@Override
	public boolean supportsForceReturn() {
		VirtualMachine machine = getVM();
		if (machine == null) {
			return false;
		}
		return machine.canForceEarlyReturn();
	}

	@Override
	public boolean supportsSelectiveGarbageCollection() {
		return fSupportsDisableGC;
	}

	/**
	 * Sets whether this target supports selectively disabling/enabling garbage
	 * collection of specific objects.
	 *
	 * @param enableGC
	 *            whether this target supports selective GC
	 */
	void setSupportsSelectiveGarbageCollection(boolean enableGC) {
		fSupportsDisableGC = enableGC;
	}

	@Override
	public String getVMName() throws DebugException {
		VirtualMachine vm = getVM();
		if (vm == null) {
			requestFailed(JDIDebugModelMessages.JDIDebugTarget_2,
					new VMDisconnectedException());
		}
		try {
			return vm.name();
		} catch (RuntimeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIDebugTarget_2, e);
			// execution will not reach this line, as
			// #targetRequestFailed will throw an exception
			return null;
		}
	}

	@Override
	public String getVersion() throws DebugException {
		VirtualMachine vm = getVM();
		if (vm == null) {
			requestFailed(JDIDebugModelMessages.JDIDebugTarget_4,
					new VMDisconnectedException());
		}
		try {
			return vm.version();
		} catch (RuntimeException e) {
			targetRequestFailed(JDIDebugModelMessages.JDIDebugTarget_4, e);
			// execution will not reach this line, as
			// #targetRequestFailed will throw an exception
			return null;
		}
	}

	@Override
	public void refreshState() throws DebugException {
		if (isTerminated() || isDisconnected()) {
			return;
		}
		boolean prevSuspend = isSuspended();
		int running = 0;
		List<JDIThread> toSuspend = new ArrayList<>();
		List<JDIThread> toResume = new ArrayList<>();
		List<JDIThread> toRefresh = new ArrayList<>();
		Iterator<JDIThread> iterator = getThreadIterator();
		while (iterator.hasNext()) {
			JDIThread thread = iterator.next();
			boolean modelSuspended = thread.isSuspended();
			ThreadReference reference = thread.getUnderlyingThread();
			try {
				boolean realSuspended = reference.isSuspended();
				if (realSuspended) {
					if (modelSuspended) {
						// Even if the model is suspended, it might be in a
						// different location so refresh
						toRefresh.add(thread);
					} else {
						// The thread is actually suspended, refresh frames and
						// fire suspend event.
						toSuspend.add(thread);
					}
				} else {
					running++;
					if (modelSuspended) {
						// thread is actually running, model is suspended,
						// resume model
						toResume.add(thread);
					}
					// else both are running - OK
				}
			} catch (InternalException e) {
				requestFailed(e.getMessage(), e);
			}
		}
		// if the entire target changed state/fire events at target level, else
		// fire thread events
		boolean targetLevelEvent = false;
		if (prevSuspend) {
			if (running > 0) {
				// was suspended, but now a thread is running
				targetLevelEvent = true;
			}
		} else {
			if (running == 0) {
				// was running, but now all threads are suspended
				targetLevelEvent = true;
			}
		}
		if (targetLevelEvent) {
			iterator = toSuspend.iterator();
			while (iterator.hasNext()) {
				JDIThread thread = iterator.next();
				thread.suspendedByVM();
			}
			iterator = toResume.iterator();
			while (iterator.hasNext()) {
				JDIThread thread = iterator.next();
				thread.resumedByVM();
			}
			iterator = toRefresh.iterator();
			while (iterator.hasNext()) {
				JDIThread thread = iterator.next();
				thread.preserveStackFrames();
			}
			if (running == 0) {
				synchronized (this) {
					setSuspended(true);
				}
				fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
			} else {
				synchronized (this) {
					setSuspended(false);
				}
				fireResumeEvent(DebugEvent.CLIENT_REQUEST);
			}
		} else {
			iterator = toSuspend.iterator();
			while (iterator.hasNext()) {
				JDIThread thread = iterator.next();
				thread.preserveStackFrames();
				thread.setRunning(false);
				thread.fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
			}
			iterator = toResume.iterator();
			while (iterator.hasNext()) {
				JDIThread thread = iterator.next();
				thread.setRunning(true);
				thread.fireResumeEvent(DebugEvent.CLIENT_REQUEST);
			}
			iterator = toRefresh.iterator();
			while (iterator.hasNext()) {
				JDIThread thread = iterator.next();
				thread.preserveStackFrames();
				thread.fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
			}
		}

	}

	@Override
	public byte[] sendCommand(byte commandSet, byte commandId, byte[] data)
			throws DebugException {
		try {
			return sendJDWPCommand(commandSet, commandId, data);
		} catch (IOException e) {
			requestFailed(e.getMessage(), e);
		}
		return null;
	}

	@Override
	public void addHotCodeReplaceListener(IJavaHotCodeReplaceListener listener) {
		fHCRListeners.add(listener);
	}

	@Override
	public void removeHotCodeReplaceListener(
			IJavaHotCodeReplaceListener listener) {
		fHCRListeners.remove(listener);
	}

	/**
	 * Returns the current hot code replace listeners.
	 *
	 * @return registered hot code replace listeners
	 * @since 3.10
	 */
	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--;
			}
		}
	}
}
