[platform] accurate detection of parallel-capable class loaders (IDEA-154504)

This commit is contained in:
Roman Shevchenko
2016-04-13 13:19:56 +02:00
parent ca2374886a
commit 743f3d973d
2 changed files with 25 additions and 11 deletions
@@ -352,15 +352,15 @@ public final class HttpRequests {
}
private static <T> T process(RequestBuilderImpl builder, RequestProcessor<T> processor) throws IOException {
if (!UrlClassLoader.PARALLEL_CAPABLE) {
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
if (!UrlClassLoader.isRegisteredAsParallelCapable(contextLoader)) {
// hack-around for class loader lock in sun.net.www.protocol.http.NegotiateAuthentication (IDEA-131621)
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
try (URLClassLoader cl = new URLClassLoader(new URL[0], oldClassLoader)) {
try (URLClassLoader cl = new URLClassLoader(new URL[0], contextLoader)) {
Thread.currentThread().setContextClassLoader(cl);
return doProcess(builder, processor);
}
finally {
Thread.currentThread().setContextClassLoader(oldClassLoader);
Thread.currentThread().setContextClassLoader(contextLoader);
}
}
else {
@@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
@@ -45,20 +46,31 @@ import java.util.List;
public class UrlClassLoader extends ClassLoader {
public static final String CLASS_EXTENSION = ".class";
public static final boolean PARALLEL_CAPABLE;
private static final boolean HAS_PARALLEL_LOADERS = SystemInfo.isJavaVersionAtLeast("1.7") && !SystemInfo.isIbmJvm;
static {
boolean parallelCapable = false;
if (SystemInfo.isJavaVersionAtLeast("1.7") && !SystemInfo.isIbmJvm) {
if (HAS_PARALLEL_LOADERS) {
try {
// todo Patches.USE_REFLECTION_TO_ACCESS_JDK7
//todo Patches.USE_REFLECTION_TO_ACCESS_JDK7
Method registerAsParallelCapable = ClassLoader.class.getDeclaredMethod("registerAsParallelCapable");
registerAsParallelCapable.setAccessible(true);
registerAsParallelCapable.invoke(null);
parallelCapable = true;
}
catch (Exception ignored) { }
}
PARALLEL_CAPABLE = parallelCapable;
}
public static boolean isRegisteredAsParallelCapable(@NotNull ClassLoader loader) {
if (!HAS_PARALLEL_LOADERS) return false;
try {
//todo Patches.USE_REFLECTION_TO_ACCESS_JDK7
Field parallelLockMap = ClassLoader.class.getDeclaredField("parallelLockMap");
parallelLockMap.setAccessible(true);
return parallelLockMap.get(loader) != null;
}
catch (Exception e) {
throw new AssertionError("Internal error: ClassLoader implementation has been altered");
}
}
private static final boolean ourClassPathIndexEnabled = Boolean.parseBoolean(System.getProperty("idea.classpath.index.enabled", "true"));
@@ -161,7 +173,7 @@ public class UrlClassLoader extends ClassLoader {
});
myClassPath = createClassPath(builder);
myAllowBootstrapResources = builder.myAllowBootstrapResources;
myClassNameInterner = PARALLEL_CAPABLE ? new WeakStringInterner() : null;
myClassNameInterner = isRegisteredAsParallelCapable(this) ? new WeakStringInterner() : null;
}
@NotNull
@@ -332,6 +344,8 @@ public class UrlClassLoader extends ClassLoader {
else return "";
}
// called by a parent class on Java 7+
@SuppressWarnings("unused")
protected Object getClassLoadingLock(String className) {
return myClassNameInterner != null ? myClassNameInterner.intern(new String(className)) : this;
}