diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java index 58f835ef11..528d691dc1 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.core.resources.IFile; @@ -134,7 +135,7 @@ public class JDIDebugTarget extends JDIDebugElement implements * TODO investigate making this a synchronized collection, to remove all this copying * @see #getThreadIterator() */ - private List fThreads; + private final List fThreads; /** * List of thread groups in this target. @@ -154,55 +155,55 @@ public class JDIDebugTarget extends JDIDebugElement implements * example, a VM that was attached to remotely may not allow the user to * terminate it. */ - private boolean fSupportsTerminate; + private final boolean fSupportsTerminate; /** * Whether terminated */ - private boolean fTerminated; + private volatile boolean fTerminated; /** * Whether in the process of terminating */ - private boolean fTerminating; + private volatile boolean fTerminating; /** * Whether in the process of disconnecting */ - private boolean fDisconnecting; + private volatile boolean fDisconnecting; /** * Whether disconnected */ - private boolean fDisconnected; + private volatile boolean fDisconnected; /** * Whether disconnect is supported. */ - private boolean fSupportsDisconnect; + private final boolean fSupportsDisconnect; /** * Whether enable/disable object GC is allowed */ - private boolean fSupportsDisableGC; + private volatile boolean fSupportsDisableGC; /** * Collection of breakpoints added to this target. Values are of type * IJavaBreakpoint. */ - private List fBreakpoints; + private final List fBreakpoints; /** * Collection of types that have attempted HCR, but failed. The types are * stored by their fully qualified names. */ - private Set fOutOfSynchTypes; + private final Set fOutOfSynchTypes; /** * Whether or not this target has performed a hot code replace. */ - private boolean fHasHCROccurred; + private volatile boolean fHasHCROccurred; /** * The name of this target - set by the client on creation, or retrieved * from the underlying VM. */ - private String fName; + private volatile String fName; /** * The event dispatcher for this debug target, which runs in its own thread. @@ -222,22 +223,22 @@ public class JDIDebugTarget extends JDIDebugElement implements /** * Whether this VM is suspended. */ - private boolean fSuspended = true; + private volatile boolean fSuspended = true; /** * Whether the VM should be resumed on startup */ - private boolean fResumeOnStartup; + private volatile boolean fResumeOnStartup; /** * The launch this target is contained in */ - private ILaunch fLaunch; + private final ILaunch fLaunch; /** * Count of the number of suspend events in this target */ - private int fSuspendCount; + private final AtomicInteger fSuspendCount = new AtomicInteger(0); /** Number of extra VM.resume operations needed due SUSPEND_VM breakpoints */ private final AtomicInteger extraResumeCount = new AtomicInteger(0); @@ -246,18 +247,18 @@ public class JDIDebugTarget extends JDIDebugElement implements * Evaluation engine cache by Java project. Engines are disposed when this * target terminates. */ - private Map fEngines; + private final Map fEngines = new HashMap<>(2); /** * List of step filters - each string is a pattern/fully qualified name of a * type to filter. */ - private String[] fStepFilters; + private volatile String[] fStepFilters; /** * Step filter state mask. */ - private int fStepFilterMask; + private volatile int fStepFilterMask; /** * Step filter bit mask - indicates if step filters are enabled. @@ -308,7 +309,7 @@ public class JDIDebugTarget extends JDIDebugElement implements /** * Whether this debug target is currently performing a hot code replace */ - private boolean fIsPerformingHotCodeReplace; + private volatile boolean fIsPerformingHotCodeReplace; /** * Target specific HCR listeners @@ -320,7 +321,7 @@ public class JDIDebugTarget extends JDIDebugElement implements /** * Java scope of the current launch, "null" means everything is in scope */ - private IJavaSearchScope fScope; + private final IJavaSearchScope fScope; /** * Java projects of the current launch, "null" means everything is in scope @@ -330,7 +331,7 @@ public class JDIDebugTarget extends JDIDebugElement implements /** * Java types from breakpoints with the flag if they are in scope for current launch */ - private Map fKnownTypes = new HashMap<>(); + private final Map fKnownTypes = new ConcurrentHashMap<>(); /** * Labels given by the user is stored in this map, where the key is the unique ID of the object. @@ -358,11 +359,11 @@ public JDIDebugTarget(ILaunch launch, VirtualMachine jvm, String name, boolean supportTerminate, boolean supportDisconnect, IProcess process, boolean resume) { super(null); - setLaunch(launch); + fLaunch = launch; setResumeOnStartup(resume); - setSupportsTerminate(supportTerminate); - setSupportsDisconnect(supportDisconnect); - setVM(jvm); + fSupportsTerminate = supportTerminate; + fSupportsDisconnect = supportDisconnect; + fVirtualMachine = jvm; jvm.setDebugTraceMode(VirtualMachine.TRACE_NONE); setProcess(process); setTerminated(false); @@ -370,11 +371,11 @@ public JDIDebugTarget(ILaunch launch, VirtualMachine jvm, String name, setDisconnected(false); setDisconnecting(false); setName(name); - prepareBreakpointsSearchScope(); - setBreakpoints(new ArrayList<>(5)); - setThreadList(new ArrayList<>()); - fGroups = new ArrayList<>(5); - setOutOfSynchTypes(new ArrayList<>(0)); + fScope = prepareBreakpointsSearchScope(); + fBreakpoints = Collections.synchronizedList(new ArrayList<>(5)); + fThreads = Collections.synchronizedList(new ArrayList<>()); + fGroups = Collections.synchronizedList(new ArrayList<>(5)); + fOutOfSynchTypes = Collections.synchronizedSet(new HashSet<>()); setHCROccurred(false); initialize(); DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this); @@ -383,7 +384,7 @@ public JDIDebugTarget(ILaunch launch, VirtualMachine jvm, String name, } - private void prepareBreakpointsSearchScope() { + private IJavaSearchScope prepareBreakpointsSearchScope() { boolean enableFiltering = Platform.getPreferencesService().getBoolean( JDIDebugPlugin.getUniqueIdentifier(), JDIDebugModel.PREF_FILTER_BREAKPOINTS_FROM_UNRELATED_SOURCES, @@ -391,33 +392,32 @@ private void prepareBreakpointsSearchScope() { null); ILaunchConfiguration config = getLaunch().getLaunchConfiguration(); if (!enableFiltering || config == null) { - return; + return null; } try { // See IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH boolean defaultClasspath = config.getAttribute("org.eclipse.jdt.launching.DEFAULT_CLASSPATH", true); //$NON-NLS-1$ if(!defaultClasspath){ - return; + return null; } IResource[] resources = config.getMappedResources(); if (resources != null && resources.length != 0) { Set javaProjects = getJavaProjects(resources); fProjects = collectReferencedJavaProjects(javaProjects); - fScope = createSourcesOnlyScope(); - return; + return createSourcesOnlyScope(); } // 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 javaProjects = getJavaProjects(ResourcesPlugin.getWorkspace().getRoot().getProject(projectName)); fProjects = collectReferencedJavaProjects(javaProjects); - fScope = createSourcesOnlyScope(); - return; + return createSourcesOnlyScope(); } } catch (CoreException e) { logError(e); } + return null; } private IJavaSearchScope createSourcesOnlyScope() { @@ -464,19 +464,6 @@ private Iterator getThreadIterator() { 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 threads) { - fThreads = threads; - } - /** * Returns the collection of breakpoints installed in this debug target. * @@ -487,17 +474,6 @@ public List 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 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 @@ -753,17 +729,6 @@ protected boolean supportsDisconnect() { return fSupportsDisconnect; } - /** - * Sets whether this debug target supports disconnection. Set on creation. - * - * @param supported - * true if this target supports disconnection, - * otherwise false - */ - private void setSupportsDisconnect(boolean supported) { - fSupportsDisconnect = supported; - } - /** * Returns whether this debug target supports termination. * @@ -773,17 +738,6 @@ protected boolean supportsTerminate() { return fSupportsTerminate; } - /** - * Sets whether this debug target supports termination. Set on creation. - * - * @param supported - * true if this target supports termination, - * otherwise false - */ - private void setSupportsTerminate(boolean supported) { - fSupportsTerminate = supported; - } - @Override public boolean supportsHotCodeReplace() { return supportsJ9HotCodeReplace() || supportsJDKHotCodeReplace(); @@ -928,17 +882,6 @@ 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. */ @@ -950,14 +893,6 @@ public void removeOutOfSynchTypes(List qualifiedNames) { fOutOfSynchTypes.removeAll(qualifiedNames); } - /** - * Sets the list of out of synch types to the given list. - */ - private void setOutOfSynchTypes(List 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. @@ -970,7 +905,7 @@ public void addOutOfSynchTypes(List qualifiedNames) { * Returns whether the given type is out of synch in this target. */ public boolean isOutOfSynch(String qualifiedName) { - if (fOutOfSynchTypes == null || fOutOfSynchTypes.isEmpty()) { + if (fOutOfSynchTypes.isEmpty()) { return false; } return fOutOfSynchTypes.contains(qualifiedName); @@ -1006,7 +941,7 @@ public boolean mayBeOutOfSynch() { * HCR has failed if there are any out of synch types */ public boolean hasHCRFailed() { - return fOutOfSynchTypes != null && !fOutOfSynchTypes.isEmpty(); + return !fOutOfSynchTypes.isEmpty(); } /** @@ -1421,23 +1356,18 @@ public boolean supportsResource(Callable typeNameSupplier, IResource res } } - Map 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); + Boolean known = fKnownTypes.get(typeName); if(known != null){ return known.booleanValue(); } boolean supportedBreakpoint = !hasMultipleMatchesInWorkspace(typeName); - knownTypes.put(typeName, Boolean.valueOf(supportedBreakpoint)); + fKnownTypes.put(typeName, Boolean.valueOf(supportedBreakpoint)); return supportedBreakpoint; } } @@ -1881,23 +1811,20 @@ protected void cleanup() { removeAllBreakpoints(); DebugPlugin.getDefault().getBreakpointManager().enableTriggerPoints(null, true); fOutOfSynchTypes.clear(); - if (fEngines != null) { - Iterator engines = fEngines.values().iterator(); - while (engines.hasNext()) { - IAstEvaluationEngine engine = engines - .next(); - engine.dispose(); - } - fEngines.clear(); + Iterator 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; + fKnownTypes.clear(); fProjects = null; - fScope = null; + fBreakpoints.clear(); } /** @@ -2820,23 +2747,13 @@ 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; + return fSuspendCount.get(); } /** @@ -2849,7 +2766,7 @@ protected int getSuspendCount() { */ protected void incrementSuspendCount(int eventDetail) { if (eventDetail != DebugEvent.EVALUATION_IMPLICIT) { - fSuspendCount++; + fSuspendCount.getAndIncrement(); } } @@ -2862,11 +2779,7 @@ protected void incrementSuspendCount(int eventDetail) { * @return evaluation engine */ public IAstEvaluationEngine getEvaluationEngine(IJavaProject project) { - if (fEngines == null) { - fEngines = new HashMap<>(2); - } - IAstEvaluationEngine engine = fEngines - .get(project); + IAstEvaluationEngine engine = fEngines.get(project); if (engine == null) { engine = EvaluationManager.newAstEvaluationEngine(project, this); fEngines.put(project, engine);