From 7fe4fdf62f16b7e7f2da38ff73516e3472c410f5 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 8 Jun 2015 13:58:22 +0300 Subject: [PATCH] correct field names/modifiers in reflection access --- .../codeInsight/javadoc/ColorUtil.java | 4 +- .../psi/impl/source/CharTableImpl.java | 2 +- .../src/com/intellij/ide/SwingCleanuper.java | 26 +++-- .../ui/impl/DialogWrapperPeerImpl.java | 95 +++---------------- .../ui/playback/commands/KeyStrokeMap.java | 4 +- .../testFramework/UsefulTestCase.java | 2 +- .../src/com/intellij/util/ReflectionUtil.java | 35 ++++++- .../util/concurrency/AtomicFieldUpdater.java | 4 +- .../idea/maven/server/MavenLeakDetector.java | 4 +- 9 files changed, 65 insertions(+), 111 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java index ac2fe33d0e43..0436cd96dbc1 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -101,7 +101,7 @@ public class ColorUtil { PsiField psiField = (PsiField)psiElement; final PsiClass psiClass = psiField.getContainingClass(); if (psiClass != null && "java.awt.Color".equals(psiClass.getQualifiedName())) { - Color c = ReflectionUtil.getField(Color.class, null, Color.class, psiField.getName()); + Color c = ReflectionUtil.getStaticFieldValue(Color.class, Color.class, psiField.getName()); if (c != null) { buffer.append(generatePreviewHtml(c)); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java index b21e68e93d8f..8462a835e393 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java @@ -207,7 +207,7 @@ public class CharTableImpl implements CharTable { for (Field field : aClass.getDeclaredFields()) { if ((field.getModifiers() & Modifier.STATIC) == 0) continue; if ((field.getModifiers() & Modifier.PUBLIC) == 0) continue; - String typeName = ReflectionUtil.getField(aClass, null, String.class, field.getName()); + String typeName = ReflectionUtil.getStaticFieldValue(aClass, String.class, field.getName()); if (typeName != null) { staticIntern(typeName); } diff --git a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java index 6c6e7245c49e..93dc1eb87b2d 100644 --- a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java +++ b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -94,7 +94,7 @@ public final class SwingCleanuper implements ApplicationComponent{ public void run() { // KeyboardFocusManager.newFocusOwner - resetStaticField(KeyboardFocusManager.class, "newFocusOwner"); + ReflectionUtil.resetStaticField(KeyboardFocusManager.class, "newFocusOwner"); // Clear "realOppositeComponent", "realOppositeWindow" final KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); @@ -105,8 +105,8 @@ public final class SwingCleanuper implements ApplicationComponent{ // Memory leak on static field in BasicPopupMenuUI try { - final Object helperObject = ReflectionUtil.getField(BasicPopupMenuUI.class, null, Object.class, "menuKeyboardHelper"); - if (null != helperObject) { + Object helperObject = ReflectionUtil.getStaticFieldValue(BasicPopupMenuUI.class, Object.class, "menuKeyboardHelper"); + if (helperObject != null) { resetField(helperObject, Component.class, "lastFocused"); } } @@ -117,11 +117,10 @@ public final class SwingCleanuper implements ApplicationComponent{ // Memory leak on javax.swing.TransferHandler$SwingDragGestureRecognizer.component try{ - final Object recognizerObject = ReflectionUtil.getField(TransferHandler.class, null, null, "recognizer"); + DragGestureRecognizer recognizer = ReflectionUtil.getStaticFieldValue(TransferHandler.class, DragGestureRecognizer.class, "recognizer"); - if(recognizerObject!=null){ // that is memory leak - final Method setComponentMethod = DragGestureRecognizer.class.getDeclaredMethod("setComponent", Component.class); - setComponentMethod.invoke(recognizerObject,new Object[]{null}); + if (recognizer != null) { // that is memory leak + recognizer.setComponent(null); } } catch (Exception e){ @@ -144,9 +143,9 @@ public final class SwingCleanuper implements ApplicationComponent{ // Ignore } - resetStaticField(KeyboardFocusManager.class, "newFocusOwner"); - resetStaticField(KeyboardFocusManager.class, "permanentFocusOwner"); - resetStaticField(KeyboardFocusManager.class, "currentFocusCycleRoot"); + ReflectionUtil.resetStaticField(KeyboardFocusManager.class, "newFocusOwner"); + ReflectionUtil.resetStaticField(KeyboardFocusManager.class, "permanentFocusOwner"); + ReflectionUtil.resetStaticField(KeyboardFocusManager.class, "currentFocusCycleRoot"); } } ); @@ -248,9 +247,6 @@ public final class SwingCleanuper implements ApplicationComponent{ // Ignore } } - private static void resetStaticField(@NotNull Class aClass, @NotNull @NonNls String name) { - ReflectionUtil.resetField(aClass, null, name); - } public final void disposeComponent(){} @@ -262,7 +258,7 @@ public final class SwingCleanuper implements ApplicationComponent{ public final void initComponent() { } private static void fixJTextComponentMemoryLeak() { - final JTextComponent component = ReflectionUtil.getField(JTextComponent.class, null, JTextComponent.class, "focusedComponent"); + final JTextComponent component = ReflectionUtil.getStaticFieldValue(JTextComponent.class, JTextComponent.class, "focusedComponent"); if (component != null && !component.isDisplayable()){ ReflectionUtil.resetField(JTextComponent.class, JTextComponent.class, "focusedComponent"); } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index 245b70aa5865..eb9958e194d1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -19,7 +19,6 @@ import com.intellij.ide.DataManager; import com.intellij.ide.IdeEventQueue; import com.intellij.ide.impl.TypeSafeDataProviderAdapter; import com.intellij.ide.ui.UISettings; -import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; @@ -38,7 +37,9 @@ import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.ui.popup.StackingPopupDispatcher; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.wm.*; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.IdeFrameImpl; @@ -276,8 +277,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra runnable.run(); } myDisposeActions.clear(); - final JRootPane root = myDialog.getRootPane(); - Runnable disposer = new Runnable() { @Override public void run() { @@ -287,20 +286,15 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - if (myDialog != null && root != null) { - myDialog.remove(root); + if (myDialog != null && myDialog.getRootPane() != null) { + myDialog.remove(myDialog.getRootPane()); } } }); } }; - if (EventQueue.isDispatchThread()) { - disposer.run(); - } - else { - SwingUtilities.invokeLater(disposer); - } + UIUtil.invokeLaterIfNeeded(disposer); } private boolean isProgressDialog() { @@ -867,12 +861,12 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra if (rootPane != null) { // Workaround for bug in native code to hold rootPane try { - ReflectionUtil.resetField(rootPane.getClass(), null, "glassPane"); - ReflectionUtil.resetField(rootPane.getClass(), null, "contentPane"); + ReflectionUtil.resetField(rootPane, "glassPane"); + ReflectionUtil.resetField(rootPane, "contentPane"); rootPane = null; - ReflectionUtil.resetField(Window.class, null, "windowListener"); + ReflectionUtil.resetField(this, "windowListener"); } catch (Exception ignored) { } @@ -880,8 +874,10 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra // http://bugs.sun.com/view_bug.do?bug_id=6614056 try { - final List list = ReflectionUtil.getField(Dialog.class, null, null, "modalDialogs"); - list.remove(this); + synchronized (getTreeLock()) { + List list = ReflectionUtil.getStaticFieldValue(Dialog.class, List.class, "modalDialogs"); + list.remove(this); + } } catch (final Exception ignored) { } @@ -1083,71 +1079,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra return wrapper != null && PlatformDataKeys.UI_DISPOSABLE.is(dataId) ? wrapper.getDisposable() : null; } } - - - private class MyFocusCommand extends FocusCommand implements KeyEventProcessor { - - private Context myContextOnFinish; - private final List myEvents = new ArrayList(); - private final DialogWrapper myWrapper; - - private MyFocusCommand(DialogWrapper wrapper) { - myWrapper = getDialogWrapper(); - setToInvalidateRequestors(false); - - Disposer.register(wrapper.getDisposable(), new Disposable() { - @Override - public void dispose() { - if (!myTypeAheadDone.isProcessed()) { - myTypeAheadDone.setDone(); - } - - flushEvents(); - } - }); - } - - @Override - @NotNull - public ActionCallback run() { - return myTypeAheadDone; - } - - @Override - public KeyEventProcessor getProcessor() { - return this; - } - - @Override - public Boolean dispatch(@NotNull KeyEvent e, @NotNull Context context) { - if (myWrapper == null || myTypeAheadDone.isProcessed()) return null; - - myEvents.addAll(context.getQueue()); - context.getQueue().clear(); - - if (isToDispatchToDialogNow(e)) { - return false; - } else { - myEvents.add(e); - return true; - } - } - - private boolean isToDispatchToDialogNow(KeyEvent e) { - return e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_ESCAPE || e.getKeyCode() == KeyEvent.VK_TAB; - } - - @Override - public void finish(@NotNull Context context) { - myContextOnFinish = context; - } - - private void flushEvents() { - if (myWrapper.isToDispatchTypeAhead() && myContextOnFinish != null) { - myContextOnFinish.dispatch(myEvents); - } - } - } } private static void setupSelectionOnPreferredComponent(final JComponent component) { diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStrokeMap.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStrokeMap.java index edc6300e97d4..bc40b8046d77 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStrokeMap.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStrokeMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -73,7 +73,7 @@ public class KeyStrokeMap { } if (symbol.length() > 1) { - final Integer code = (Integer)ReflectionUtil.getField(KeyEvent.class, null, int.class, "VK_" + StringUtil.toUpperCase(symbol)); + final Integer code = ReflectionUtil.getStaticFieldValue(KeyEvent.class, int.class, "VK_" + StringUtil.toUpperCase(symbol)); if (code == null) { return throwUnrecognized(symbol); } diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 8f020307e100..0d4eb1a81cda 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -186,7 +186,7 @@ public abstract class UsefulTestCase extends TestCase { catch (Exception e) { throw new RuntimeException(e); } - Set files = ReflectionUtil.getField(aClass, null, Set.class, "files"); + Set files = ReflectionUtil.getStaticFieldValue(aClass, Set.class, "files"); DELETE_ON_EXIT_HOOK_CLASS = aClass; DELETE_ON_EXIT_HOOK_DOT_FILES = files; } diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java index 463089167671..e3a61dc31a20 100644 --- a/platform/util/src/com/intellij/util/ReflectionUtil.java +++ b/platform/util/src/com/intellij/util/ReflectionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,7 +20,7 @@ import com.intellij.Patches; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.DifferenceFilter; -import com.intellij.util.containers.*; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -211,6 +211,7 @@ public class ReflectionUtil { LOG.info(e); } } + public static void resetField(@NotNull Object object, @Nullable("null means any type") Class type, @NotNull String name) { try { resetField(object, findField(object.getClass(), type, name)); @@ -256,6 +257,10 @@ public class ReflectionUtil { } } + public static void resetStaticField(@NotNull Class aClass, @NotNull @NonNls String name) { + resetField(aClass, null, name); + } + @Nullable public static Method findMethod(@NotNull Collection methods, @NonNls @NotNull String name, @NotNull Class... parameters) { for (final Method method : methods) { @@ -332,7 +337,7 @@ public class ReflectionUtil { return method == null ? null : method.getDeclaringClass(); } - public static T getField(@NotNull Class objectClass, Object object, @Nullable("null means any type") Class fieldType, @NotNull @NonNls String fieldName) { + public static T getField(@NotNull Class objectClass, @Nullable Object object, @Nullable("null means any type") Class fieldType, @NotNull @NonNls String fieldName) { try { final Field field = findAssignableField(objectClass, fieldType, fieldName); return (T)field.get(object); @@ -347,8 +352,30 @@ public class ReflectionUtil { } } + public static T getStaticFieldValue(@NotNull Class objectClass, @Nullable("null means any type") Class fieldType, @NotNull @NonNls String fieldName) { + try { + final Field field = findAssignableField(objectClass, fieldType, fieldName); + if (!Modifier.isStatic(field.getModifiers())) { + throw new IllegalArgumentException("Field " + objectClass + "." + fieldName + " is not static"); + } + return (T)field.get(null); + } + catch (NoSuchFieldException e) { + LOG.debug(e); + return null; + } + catch (IllegalAccessException e) { + LOG.debug(e); + return null; + } + } + // returns true if value was set - public static boolean setField(@NotNull Class objectClass, Object object, @Nullable("null means any type") Class fieldType, @NotNull @NonNls String fieldName, T value) { + public static boolean setField(@NotNull Class objectClass, + Object object, + @Nullable("null means any type") Class fieldType, + @NotNull @NonNls String fieldName, + T value) { try { final Field field = findAssignableField(objectClass, fieldType, fieldName); field.set(object, value); diff --git a/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java b/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java index fbac0f06cd39..eea178befdce 100644 --- a/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java +++ b/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -39,7 +39,7 @@ public class AtomicFieldUpdater { @NotNull public static Unsafe getUnsafe() { - Unsafe unsafe = ReflectionUtil.getField(Unsafe.class, null, Unsafe.class, "theUnsafe"); + Unsafe unsafe = ReflectionUtil.getStaticFieldValue(Unsafe.class, Unsafe.class, "theUnsafe"); if (unsafe == null) { throw new RuntimeException("Could not find 'theUnsafe' field in the " + Unsafe.class); } diff --git a/plugins/maven/maven3-server-common/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java b/plugins/maven/maven3-server-common/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java index a51ddfe0210a..f3f835ae6167 100644 --- a/plugins/maven/maven3-server-common/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java +++ b/plugins/maven/maven3-server-common/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -63,6 +63,6 @@ public class MavenLeakDetector { // we can ignore this one return Collections.emptyMap(); } - return ReflectionUtil.getField(clazz, null, Map.class, "hooks"); + return ReflectionUtil.getStaticFieldValue(clazz, Map.class, "hooks"); } }