Skip to content

Commit

Permalink
Defer initialization of classpath to the background if called from main
Browse files Browse the repository at this point in the history
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 #1481
  • Loading branch information
laeubi committed Dec 17, 2024
1 parent 85ceed2 commit 4639a5e
Showing 1 changed file with 54 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,32 @@
*******************************************************************************/
package org.eclipse.pde.internal.core;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jdt.core.ClasspathContainerInitializer;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.pde.core.plugin.IPluginModelBase;

public class RequiredPluginsInitializer extends ClasspathContainerInitializer {

private static final AtomicBoolean WARNING_LOGGED = new AtomicBoolean();

private static final Map<IJavaProject, Job> JOB_MAP = new ConcurrentHashMap<>();

private static final Job initPDEJob = Job.create(PDECoreMessages.PluginModelManager_InitializingPluginModels,
monitor -> {
if (!PDECore.getDefault().getModelManager().isInitialized()) {
Expand All @@ -36,6 +48,48 @@ public class RequiredPluginsInitializer extends ClasspathContainerInitializer {

@Override
public void initialize(IPath containerPath, IJavaProject javaProject) throws CoreException {
if ("main".equals(Thread.currentThread().getName())) { //$NON-NLS-1$
// See https://github.com/eclipse-pde/eclipse.pde/issues/1481
if (WARNING_LOGGED.compareAndSet(false, true)) {
ILog.get().warn(
"RequiredPluginsInitializer called from within the UI thread this will badly impact your IDE performance!", //$NON-NLS-1$
new RuntimeException("Called from main thread here")); //$NON-NLS-1$
}
JOB_MAP.compute(javaProject, (jp, oldjob) -> {
if (oldjob != null) {
oldjob.cancel();
}
Job job = Job.create(PDECoreMessages.PluginModelManager_InitializingPluginModels, m -> {
if (oldjob != null) {
try {
oldjob.join();
} catch (InterruptedException e) {
}
}
setClasspath(jp);
});
job.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
JOB_MAP.remove(jp);
}
});
job.schedule();
return job;
});
return;
}
Job job = JOB_MAP.get(javaProject);
if (job != null) {
try {
job.join();
} catch (InterruptedException e) {
}
}
setClasspath(javaProject);
}

protected void setClasspath(IJavaProject javaProject) throws JavaModelException {
IProject project = javaProject.getProject();
// The first project to be built may initialize the PDE models, potentially long running, so allow cancellation
PluginModelManager manager = PDECore.getDefault().getModelManager();
Expand Down

0 comments on commit 4639a5e

Please sign in to comment.