Skip to content

Commit 69ba82e

Browse files
committed
Defer initialization of classpath to the background if called from main
Currently there are some bad behaving UI components in the eclipse IDE that trigger resolving of the classpath containers in the UI, this leads to very bad startup performance and even deadlocks in startup. This now detects the issue, logs a warning of the offending component and defer the initialization of classpath to a background job, this currently increase time from starting eclipse until UI is shown noticeable. Fix eclipse-pde#1481
1 parent 5baaa6d commit 69ba82e

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/RequiredPluginsInitializer.java

+54
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,32 @@
1313
*******************************************************************************/
1414
package org.eclipse.pde.internal.core;
1515

16+
import java.util.Map;
17+
import java.util.concurrent.ConcurrentHashMap;
18+
import java.util.concurrent.atomic.AtomicBoolean;
19+
1620
import org.eclipse.core.resources.IProject;
1721
import org.eclipse.core.runtime.CoreException;
22+
import org.eclipse.core.runtime.ILog;
1823
import org.eclipse.core.runtime.IPath;
1924
import org.eclipse.core.runtime.IStatus;
2025
import org.eclipse.core.runtime.Status;
26+
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
2127
import org.eclipse.core.runtime.jobs.Job;
28+
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
2229
import org.eclipse.jdt.core.ClasspathContainerInitializer;
2330
import org.eclipse.jdt.core.IClasspathContainer;
2431
import org.eclipse.jdt.core.IJavaProject;
2532
import org.eclipse.jdt.core.JavaCore;
33+
import org.eclipse.jdt.core.JavaModelException;
2634
import org.eclipse.pde.core.plugin.IPluginModelBase;
2735

2836
public class RequiredPluginsInitializer extends ClasspathContainerInitializer {
2937

38+
private static final AtomicBoolean WARNING_LOGGED = new AtomicBoolean();
39+
40+
private static final Map<IJavaProject, Job> JOB_MAP = new ConcurrentHashMap<>();
41+
3042
private static final Job initPDEJob = Job.create(PDECoreMessages.PluginModelManager_InitializingPluginModels,
3143
monitor -> {
3244
if (!PDECore.getDefault().getModelManager().isInitialized()) {
@@ -36,6 +48,48 @@ public class RequiredPluginsInitializer extends ClasspathContainerInitializer {
3648

3749
@Override
3850
public void initialize(IPath containerPath, IJavaProject javaProject) throws CoreException {
51+
if ("main".equals(Thread.currentThread().getName())) { //$NON-NLS-1$
52+
// See https://github.com/eclipse-pde/eclipse.pde/issues/1481
53+
if (WARNING_LOGGED.compareAndSet(false, true)) {
54+
ILog.get().warn(
55+
"RequiredPluginsInitializer called from within the UI thread this will badly impact your IDE performance!", //$NON-NLS-1$
56+
new RuntimeException("Called from main thread here")); //$NON-NLS-1$
57+
}
58+
JOB_MAP.compute(javaProject, (jp, oldjob) -> {
59+
if (oldjob != null) {
60+
oldjob.cancel();
61+
}
62+
Job job = Job.create(PDECoreMessages.PluginModelManager_InitializingPluginModels, m -> {
63+
if (oldjob != null) {
64+
try {
65+
oldjob.join();
66+
} catch (InterruptedException e) {
67+
}
68+
}
69+
setClasspath(jp);
70+
});
71+
job.addJobChangeListener(new JobChangeAdapter() {
72+
@Override
73+
public void done(IJobChangeEvent event) {
74+
JOB_MAP.remove(jp);
75+
}
76+
});
77+
job.schedule();
78+
return job;
79+
});
80+
return;
81+
}
82+
Job job = JOB_MAP.get(javaProject);
83+
if (job != null) {
84+
try {
85+
job.join();
86+
} catch (InterruptedException e) {
87+
}
88+
}
89+
setClasspath(javaProject);
90+
}
91+
92+
protected void setClasspath(IJavaProject javaProject) throws JavaModelException {
3993
IProject project = javaProject.getProject();
4094
// The first project to be built may initialize the PDE models, potentially long running, so allow cancellation
4195
PluginModelManager manager = PDECore.getDefault().getModelManager();

0 commit comments

Comments
 (0)