Почему мой объект был беззвучно изменен отладчиком IntelliJ IDEA? - PullRequest
5 голосов
/ 28 апреля 2019

Я отлаживаю (Shift + F9) метод offer(E e) API JDK8 java.util.concurrent.ConcurrentLinkedQueue,

Я обнаружил, что IntelliJ IDEA изменит поле head этой очереди беззвучно в процессе отладки,

но схема запуска (Shift + F10) не изменит поля, почему?

и нет кода, изменяющего это поле в offer(E e), это меня смущает.

Затем я попробовал другую IDE (Eclipse Mars.1 Release (4.5.1)), ноЭто не такая проблема.

Есть некоторые результаты моего теста:

  • схема запуска (Shift + F10)
head: 1159190947 
head: 1159190947 
head: 1159190947 
head: 1159190947 
  • схема отладки (шаг: F8)
head: 1989972246 
head: 1791930789 
head: 1791930789 
head: 1791930789 
  • схема отладки (Программа возобновления: F9)
head: 1989972246 
head: 1989972246 
head: 1791930789 
head: 1791930789 

информация о версии:IntelliJ IDEA 2018.1 (Ultimate Edition)Сборка № IU-181.4203.550, построена 27 марта 2018 г.JRE: 1.8.0_162-b12 amd64JVM: 64-разрядная серверная виртуальная машина Java HotSpot ™ от Oracle CorporationWindows 10 10.0

И IntelliJ IDEA 2018.2.3 (Community Edition) & IntelliJ IDEA 2019.1 (Ultimate Edition) имеет ту же проблему.

import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentLinkedQueue;

public class ConcurrentLinkedQueueTest {

    public static void main(String[] args) {
        ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
        print(queue);
        queue.offer("aaa");
        print(queue);
        queue.offer("bbb");
        print(queue);
        queue.offer("ccc");
        print(queue);
    }

    /**
     * 打印并发队列head属性的identityHashCode
     * @param queue
     */
    private static void print(ConcurrentLinkedQueue queue) {
        Field field = null;
        boolean isAccessible = false;
        try {
            field = ConcurrentLinkedQueue.class.getDeclaredField("head");
            isAccessible = field.isAccessible();
            if (!isAccessible) {
                field.setAccessible(true);
            }
            System.out.println("head: " + System.identityHashCode(field.get(queue)));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            field.setAccessible(isAccessible);
        }
    }
}

1 Ответ

5 голосов
/ 28 апреля 2019

По умолчанию IntelliJ IDEA вызывает метод toString() для объектов, чтобы получить их представление в представлении Watches. В ConcurrentLinkedQueue метод toString() перебирает коллекцию, которая может обновить поле head с помощью вызова updateHead() в методе first() (и, возможно, в других местах, я не исследовал всю реализацию .

Если вы идете в Предпочтения | Сборка, выполнение, развертывание | Отладчик | Представления данных | Java и отключите «Включить представление объекта toString ()», вы больше не должны наблюдать это поведение.

...