IDEA-106251 IDEA (EAP) fails to launch with latest jdk8 (build 87)

This commit is contained in:
Alexey Kudravtsev
2013-04-30 13:56:21 +04:00
parent 6f0466ce2d
commit ae76aa5ae5
7 changed files with 102 additions and 48 deletions
@@ -45,10 +45,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.Function;
import com.intellij.util.PlatformUtils;
import com.intellij.util.*;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.Graph;
@@ -60,7 +57,6 @@ import org.jdom.Document;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.reflect.Reflection;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
@@ -77,7 +73,6 @@ import java.util.zip.ZipInputStream;
*/
@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"}) // No logger is loaded at this time so we have to use these.
public class PluginManager {
@NonNls private static final String PROPERTY_PLUGIN_PATH = "plugin.path";
@NonNls public static final String INSTALLED_TXT = "installed.txt";
@NonNls private static final String SPECIAL_IDEA_PLUGIN = "IDEA CORE";
@@ -119,6 +114,7 @@ public class PluginManager {
}
public static void initPlugins(@Nullable StartupProgress progress) {
PluginClassLoaderDetector.install();
long start = System.currentTimeMillis();
try {
initializePlugins(progress);
@@ -224,7 +220,7 @@ public class PluginManager {
final IdeaPluginDescriptorImpl[] pluginDescriptors = loadDescriptors(progress);
final Class callerClass = Reflection.getCallerClass(1);
final Class callerClass = ReflectionUtil.getCallerClass(1);
final ClassLoader parentLoader = callerClass.getClassLoader();
final List<IdeaPluginDescriptorImpl> result = new ArrayList<IdeaPluginDescriptorImpl>();
@@ -296,7 +292,7 @@ public class PluginManager {
ourPlugins = pluginDescriptors;
}
public static void initClassLoader(final ClassLoader parentLoader, final IdeaPluginDescriptorImpl descriptor) {
public static void initClassLoader(@NotNull ClassLoader parentLoader, @NotNull IdeaPluginDescriptorImpl descriptor) {
final List<File> classPath = descriptor.getClassPath();
final ClassLoader loader =
createPluginClassLoader(classPath.toArray(new File[classPath.size()]), new ClassLoader[]{parentLoader}, descriptor);
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.extensions.PluginId;
public class PluginClassLoaderDetector implements Function<String, ClassLoader> {
private static final PluginClassLoaderDetector INSTANCE = new PluginClassLoaderDetector();
@Override
public ClassLoader fun(String className) {
PluginId pluginId = PluginManager.getPluginByClassName(className);
IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId);
if (plugin == null) return null;
return plugin.getPluginClassLoader();
}
public static void install() {
ReflectionUtil.PLUGIN_CLASS_LOADER_DETECTOR = INSTANCE;
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.reference.SoftReference;
import com.intellij.util.ImageLoader;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.RetinaImage;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.WeakHashMap;
@@ -27,7 +28,6 @@ import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.reflect.Reflection;
import javax.swing.*;
import java.awt.*;
@@ -113,18 +113,18 @@ public final class IconLoader {
@NotNull
public static Icon getIcon(@NonNls @NotNull final String path) {
int stackFrameCount = 2;
Class callerClass = Reflection.getCallerClass(stackFrameCount);
Class callerClass = ReflectionUtil.getCallerClass(stackFrameCount);
while (callerClass != null && callerClass.getClassLoader() == null) { // looks like a system class
callerClass = Reflection.getCallerClass(++stackFrameCount);
callerClass = ReflectionUtil.getCallerClass(++stackFrameCount);
}
if (callerClass == null) {
callerClass = Reflection.getCallerClass(1);
callerClass = ReflectionUtil.getCallerClass(1);
}
return getIcon(path, callerClass);
}
@Nullable
private static Icon getReflectiveIcon(String path, ClassLoader classLoader) {
private static Icon getReflectiveIcon(@NotNull String path, ClassLoader classLoader) {
try {
String pckg = path.startsWith("AllIcons.") ? "com.intellij.icons." : "icons.";
Class cur = Class.forName(pckg + path.substring(0, path.lastIndexOf('.')).replace('.', '$'), true, classLoader);
@@ -144,12 +144,12 @@ public final class IconLoader {
*/
public static Icon findIcon(@NonNls @NotNull String path) {
int stackFrameCount = 2;
Class callerClass = Reflection.getCallerClass(stackFrameCount);
Class callerClass = ReflectionUtil.getCallerClass(stackFrameCount);
while (callerClass != null && callerClass.getClassLoader() == null) { // looks like a system class
callerClass = Reflection.getCallerClass(++stackFrameCount);
callerClass = ReflectionUtil.getCallerClass(++stackFrameCount);
}
if (callerClass == null) {
callerClass = Reflection.getCallerClass(1);
callerClass = ReflectionUtil.getCallerClass(1);
}
return findIcon(path, callerClass);
}
@@ -196,10 +196,10 @@ public final class IconLoader {
private static String undeprecate(String path) {
String replacement = ourDeprecatedIconsReplacements.get(path);
return replacement != null ? replacement : path;
return replacement == null ? path : replacement;
}
private static boolean isReflectivePath(String path) {
private static boolean isReflectivePath(@NotNull String path) {
List<String> paths = StringUtil.split(path, ".");
return paths.size() > 1 && paths.get(0).endsWith("Icons");
}
@@ -218,7 +218,7 @@ public final class IconLoader {
}
@Nullable
public static Icon findIcon(String path, final ClassLoader classLoader) {
public static Icon findIcon(@NotNull String path, final ClassLoader classLoader) {
path = undeprecate(path);
if (isReflectivePath(path)) return getReflectiveIcon(path, classLoader);
if (!path.startsWith("/")) return null;
@@ -295,14 +295,17 @@ public final class IconLoader {
public static Icon getTransparentIcon(@NotNull final Icon icon, final float alpha) {
return new Icon() {
@Override
public int getIconHeight() {
return icon.getIconHeight();
}
@Override
public int getIconWidth() {
return icon.getIconWidth();
}
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
final Graphics2D g2 = (Graphics2D)g;
final Composite saveComposite = g2.getComposite();
@@ -346,14 +349,17 @@ public final class IconLoader {
return icon != null ? icon : EMPTY_ICON;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
getRealIcon().paintIcon(c, g, x, y);
}
@Override
public int getIconWidth() {
return getRealIcon().getIconWidth();
}
@Override
public int getIconHeight() {
return getRealIcon().getIconHeight();
}
@@ -369,6 +375,7 @@ public final class IconLoader {
super(image);
}
@Override
public final synchronized void paintIcon(final Component c, final Graphics g, final int x, final int y) {
super.paintIcon(null, g, x, y);
}
@@ -399,7 +406,7 @@ public final class IconLoader {
return icon != null ? icon.getIconHeight() : 0;
}
protected synchronized final Icon getOrComputeIcon() {
protected final synchronized Icon getOrComputeIcon() {
if (!myWasComputed || isDarkVariant != USE_DARK_ICONS) {
isDarkVariant = USE_DARK_ICONS;
myWasComputed = true;
@@ -420,7 +427,7 @@ public final class IconLoader {
private final Class myCallerClass;
private final String myPath;
public ByClass(Class aClass, String path) {
public ByClass(@NotNull Class aClass, @NotNull String path) {
myCallerClass = aClass;
myPath = path;
}
@@ -16,9 +16,9 @@
package com.intellij.openapi.util;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ReflectionUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import sun.reflect.Reflection;
import java.util.ArrayList;
import java.util.Collection;
@@ -51,7 +51,7 @@ public class JDOMExternalizableStringList extends ArrayList<String> implements J
for (final Object o : element.getChildren()) {
Element listElement = (Element)o;
if (ATTR_LIST.equals(listElement.getName())) {
final ClassLoader classLoader = Reflection.getCallerClass(2).getClassLoader();
final ClassLoader classLoader = ReflectionUtil.getCallerClass(2).getClassLoader();
for (final Object o1 : listElement.getChildren()) {
Element listItemElement = (Element)o1;
if (!ATTR_ITEM.equals(listItemElement.getName())) {
@@ -86,12 +86,12 @@ public class ImageLoader implements Serializable {
@Nullable
public static Image loadFromResource(@NonNls String s) {
int stackFrameCount = 2;
Class callerClass = Reflection.getCallerClass(stackFrameCount);
Class callerClass = ReflectionUtil.getCallerClass(stackFrameCount);
while (callerClass != null && callerClass.getClassLoader() == null) { // looks like a system class
callerClass = Reflection.getCallerClass(++stackFrameCount);
callerClass = ReflectionUtil.getCallerClass(++stackFrameCount);
}
if (callerClass == null) {
callerClass = Reflection.getCallerClass(1);
callerClass = ReflectionUtil.getCallerClass(1);
}
return loadFromResource(s, callerClass);
}
@@ -39,7 +39,7 @@ public class ReflectionUtil {
@Nullable
public static Type resolveVariable(TypeVariable variable, final Class classType, boolean resolveInInterfacesOnly) {
final Class aClass = getRawType(classType);
int index = ArrayUtil.find(ReflectionCache.getTypeParameters(aClass), variable);
int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), variable);
if (index >= 0) {
return variable;
}
@@ -63,7 +63,7 @@ public class ReflectionUtil {
}
if (resolved instanceof TypeVariable) {
final TypeVariable typeVariable = (TypeVariable)resolved;
index = ArrayUtil.find(ReflectionCache.getTypeParameters(anInterface), typeVariable);
index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(anInterface), typeVariable);
if (index < 0) {
LOG.error("Cannot resolve type variable:\n" + "typeVariable = " + typeVariable + "\n" + "genericDeclaration = " +
declarationToString(typeVariable.getGenericDeclaration()) + "\n" + "searching in " + declarationToString(anInterface));
@@ -73,7 +73,7 @@ public class ReflectionUtil {
return Object.class;
}
if (type instanceof ParameterizedType) {
return getActualTypeArguments(((ParameterizedType)type))[index];
return getActualTypeArguments((ParameterizedType)type)[index];
}
throw new AssertionError("Invalid type: " + type);
}
@@ -81,7 +81,7 @@ public class ReflectionUtil {
return null;
}
public static String declarationToString(final GenericDeclaration anInterface) {
public static String declarationToString(@NotNull GenericDeclaration anInterface) {
return anInterface.toString()
+ Arrays.asList(anInterface.getTypeParameters())
+ " loaded by " + ((Class)anInterface).getClassLoader();
@@ -118,9 +118,9 @@ public class ReflectionUtil {
return (Class<?>)((ParameterizedType)type).getRawType();
}
if (type instanceof TypeVariable && classType instanceof ParameterizedType) {
final int index = ArrayUtil.find(ReflectionCache.getTypeParameters(aClass), type);
final int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), type);
if (index >= 0) {
return getRawType(getActualTypeArguments(((ParameterizedType)classType))[index]);
return getRawType(getActualTypeArguments((ParameterizedType)classType)[index]);
}
}
} else {
@@ -307,21 +307,30 @@ public class ReflectionUtil {
}
}
/**
* @see com.intellij.ide.plugins.PluginManager#initPlugins(com.intellij.ide.StartupProgress)
*/
@SuppressWarnings("JavadocReference")
static volatile Function<String, ClassLoader> PLUGIN_CLASS_LOADER_DETECTOR = FunctionUtil.nullConstant();
/**
* Returns the class this method was called 'framesToSkip' frames up the caller hierarchy.
* JDK used to have {@link sun.reflect.Reflection#getCallerClass(int)} until jdk 1.8 build 87.
* So we have to resort to slow stack unwinding.
*
* NOTE:
* <b>Extremely expensive!
* Please consider not using it.
* These aren't the droids you're looking for!</b>
*/
@SuppressWarnings("JavadocReference")
@Nullable
public static Class getCallerClass(int framesToSkip) {
int adjustedFramesForThisCall = framesToSkip/*+1*/; // take into account this method frame
int frames = framesToSkip;
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
String className = null;
for (int i = 1; i<=adjustedFramesForThisCall; i++) {
for (int i = 1; i<=frames; i++) {
if (i >= stackTrace.length) {
break;
}
@@ -330,10 +339,10 @@ public class ReflectionUtil {
if (className.equals("java.lang.reflect.Method") ||
className.equals("sun.reflect.NativeMethodAccessorImpl") ||
className.equals("sun.reflect.DelegatingMethodAccessorImpl")) {
adjustedFramesForThisCall++;
frames++;
continue;
}
if (i == adjustedFramesForThisCall) {
if (i == frames) {
break;
}
}
@@ -344,15 +353,21 @@ public class ReflectionUtil {
className = ReflectionUtil.class.getName();
}
//Class realClass = Reflection.getCallerClass(adjustedFramesForThisCall+1);
//if (!realClass.getName().equals(className)) {
// int i = 0;
//}
try {
return Class.forName(className);
}
catch (ClassNotFoundException ignored) {
}
ClassLoader pluginClassLoader = PLUGIN_CLASS_LOADER_DETECTOR.fun(className);
if (pluginClassLoader != null) {
try {
return Class.forName(className, false, pluginClassLoader);
}
catch (ClassNotFoundException ignored) {
}
}
LOG.error("Could not load class '" + className + "' using classLoader " + ReflectionUtil.class.getClassLoader() + "." +
(stackTrace[1].getClassName().equals("com.intellij.openapi.util.IconLoader") ? " Use getIcon(String, Class) instead." : ""));
return null;
}
}
@@ -30,10 +30,10 @@ import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsRoot;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.reflect.Reflection;
import java.util.ArrayList;
import java.util.Collection;
@@ -105,7 +105,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
if ((! myProject.isOpen()) || myProject.isDisposed() || myVcsManager.getAllActiveVcss().length == 0) return;
if (LOG.isDebugEnabled()) {
LOG.debug("everything dirty: " + Reflection.getCallerClass(1));
LOG.debug("everything dirty: " + ReflectionUtil.getCallerClass(1));
}
final LifeDrop lifeDrop = myLife.doIfAlive(new Runnable() {
@@ -169,7 +169,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
if (! haveStuff) return;
if (LOG.isDebugEnabled()) {
LOG.debug("paths dirty: " + filesConverted + "; " + dirsConverted + "; " + Reflection.getCallerClass(2));
LOG.debug("paths dirty: " + filesConverted + "; " + dirsConverted + "; " + ReflectionUtil.getCallerClass(2));
}
takeDirt(new Consumer<DirtBuilder>() {
@@ -231,7 +231,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
if (! haveStuff) return;
if (LOG.isDebugEnabled()) {
LOG.debug("files dirty: " + filesConverted + "; " + dirsConverted + "; " + Reflection.getCallerClass(2));
LOG.debug("files dirty: " + filesConverted + "; " + dirsConverted + "; " + ReflectionUtil.getCallerClass(2));
}
takeDirt(new Consumer<DirtBuilder>() {
@@ -257,7 +257,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
final AbstractVcs vcs = myGuess.getVcsForDirty(file);
if (vcs == null) return;
if (LOG.isDebugEnabled()) {
LOG.debug("file dirty: " + file + "; " + Reflection.getCallerClass(2));
LOG.debug("file dirty: " + file + "; " + ReflectionUtil.getCallerClass(2));
}
final VcsRoot root = new VcsRoot(vcs, file);
takeDirt(new Consumer<DirtBuilder>() {
@@ -274,7 +274,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
final AbstractVcs vcs = myGuess.getVcsForDirty(file);
if (vcs == null) return;
if (LOG.isDebugEnabled()) {
LOG.debug("file dirty: " + file + "; " + Reflection.getCallerClass(1));
LOG.debug("file dirty: " + file + "; " + ReflectionUtil.getCallerClass(1));
}
final FilePathUnderVcs root = new FilePathUnderVcs(file, vcs);
takeDirt(new Consumer<DirtBuilder>() {
@@ -295,7 +295,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
final AbstractVcs vcs = myGuess.getVcsForDirty(dir);
if (vcs == null) return;
if (LOG.isDebugEnabled()) {
LOG.debug("dir dirty recursively: " + dir + "; " + Reflection.getCallerClass(2));
LOG.debug("dir dirty recursively: " + dir + "; " + ReflectionUtil.getCallerClass(2));
}
final VcsRoot root = new VcsRoot(vcs, dir);
takeDirt(new Consumer<DirtBuilder>() {
@@ -312,7 +312,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
final AbstractVcs vcs = myGuess.getVcsForDirty(path);
if (vcs == null) return;
if (LOG.isDebugEnabled()) {
LOG.debug("dir dirty recursively: " + path + "; " + Reflection.getCallerClass(2));
LOG.debug("dir dirty recursively: " + path + "; " + ReflectionUtil.getCallerClass(2));
}
final FilePathUnderVcs root = new FilePathUnderVcs(path, vcs);
takeDirt(new Consumer<DirtBuilder>() {