Skip to content

Commit 588fad8

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 process of creating 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 decrease time from starting eclipse until UI is shown noticeable. Fix eclipse-pde#1481
1 parent 5baaa6d commit 588fad8

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

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

+67
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,86 @@
1313
*******************************************************************************/
1414
package org.eclipse.pde.internal.core;
1515

16+
import java.lang.StackWalker.Option;
17+
import java.util.Map;
18+
import java.util.concurrent.ConcurrentHashMap;
19+
import java.util.concurrent.atomic.AtomicBoolean;
20+
1621
import org.eclipse.core.resources.IProject;
1722
import org.eclipse.core.runtime.CoreException;
23+
import org.eclipse.core.runtime.ILog;
1824
import org.eclipse.core.runtime.IPath;
1925
import org.eclipse.core.runtime.IStatus;
2026
import org.eclipse.core.runtime.Status;
27+
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
2128
import org.eclipse.core.runtime.jobs.Job;
29+
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
2230
import org.eclipse.jdt.core.ClasspathContainerInitializer;
2331
import org.eclipse.jdt.core.IClasspathContainer;
2432
import org.eclipse.jdt.core.IJavaProject;
2533
import org.eclipse.jdt.core.JavaCore;
34+
import org.eclipse.jdt.core.JavaModelException;
2635
import org.eclipse.pde.core.plugin.IPluginModelBase;
2736

2837
public class RequiredPluginsInitializer extends ClasspathContainerInitializer {
2938

39+
private static final AtomicBoolean WARNING_LOGGED = new AtomicBoolean();
40+
41+
private static final Map<IJavaProject, Job> JOB_MAP = new ConcurrentHashMap<>();
42+
3043
private static final Job initPDEJob = Job.create(PDECoreMessages.PluginModelManager_InitializingPluginModels,
3144
monitor -> {
3245
if (!PDECore.getDefault().getModelManager().isInitialized()) {
3346
PDECore.getDefault().getModelManager().targetReloaded(monitor);
3447
}
3548
});
3649

50+
private static StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
51+
3752
@Override
3853
public void initialize(IPath containerPath, IJavaProject javaProject) throws CoreException {
54+
if (isCalledWhileWorkbenchStartup()) {
55+
// See https://github.com/eclipse-pde/eclipse.pde/issues/1481
56+
if (WARNING_LOGGED.compareAndSet(false, true)) {
57+
ILog.get().warn(
58+
"RequiredPluginsInitializer called from within the Application startup thread this will badly impact your IDE performance!", //$NON-NLS-1$
59+
new RuntimeException("Called from Application startup thread thread here")); //$NON-NLS-1$
60+
}
61+
JOB_MAP.compute(javaProject, (jp, oldjob) -> {
62+
if (oldjob != null) {
63+
oldjob.cancel();
64+
}
65+
Job job = Job.create(PDECoreMessages.PluginModelManager_InitializingPluginModels, m -> {
66+
if (oldjob != null) {
67+
try {
68+
oldjob.join();
69+
} catch (InterruptedException e) {
70+
}
71+
}
72+
setClasspath(jp);
73+
});
74+
job.addJobChangeListener(new JobChangeAdapter() {
75+
@Override
76+
public void done(IJobChangeEvent event) {
77+
JOB_MAP.remove(jp);
78+
}
79+
});
80+
job.schedule();
81+
return job;
82+
});
83+
return;
84+
}
85+
Job job = JOB_MAP.get(javaProject);
86+
if (job != null) {
87+
try {
88+
job.join();
89+
} catch (InterruptedException e) {
90+
}
91+
}
92+
setClasspath(javaProject);
93+
}
94+
95+
protected void setClasspath(IJavaProject javaProject) throws JavaModelException {
3996
IProject project = javaProject.getProject();
4097
// The first project to be built may initialize the PDE models, potentially long running, so allow cancellation
4198
PluginModelManager manager = PDECore.getDefault().getModelManager();
@@ -85,4 +142,14 @@ public void requestClasspathContainerUpdate(IPath containerPath, IJavaProject pr
85142
JavaCore.setClasspathContainer(containerPath, new IJavaProject[] {project}, new IClasspathContainer[] {containerSuggestion}, null);
86143
}
87144

145+
private static boolean isCalledWhileWorkbenchStartup() {
146+
147+
return walker.walk(frames -> {
148+
return frames.anyMatch(sf -> {
149+
return "org.eclipse.e4.ui.internal.workbench.E4Workbench".equals(sf.getClassName()) //$NON-NLS-1$
150+
&& "createAndRunUI".equals(sf.getMethodName()); //$NON-NLS-1$
151+
});
152+
});
153+
}
154+
88155
}

0 commit comments

Comments
 (0)