Java экземпляр члена коррупции

Rami Rosenbaum спросил: 28 апреля 2018 в 09:44 в: java

У меня есть многопоточное приложение Java 1.6 (5-7 потоков, большинство простоя), что имеет странное поведение.
В поток входит обновление устройства с 4-байтным идентификатором.
Я придерживаюсь ID в приватном байтовом массиве. Когда обновление завершается успешно, через ~ 4 секунды устройство отправляет сообщение STATUS, в котором я сравниваю его ID с тем, который я держу, и очищаю частный массив укусов и отключает таймер с ошибкой.
Все работа выполняется в экземпляре класса singleton.

Странное поведение:
Я печатаю значение частного байтового массива из метода, который вызывается периодически. в течение 4 секунд, ожидающих сообщения STATUS, в журнале отображается другой идентификатор (а не мусор, а 4-байтовый идентификатор другого объекта). Проверка значения с точкой останова показывает это недопустимое значение (это означает, что это не ошибка журнала).
Но, однако, когда приходит сообщение STATUS, я сравниваю ID с тем, который я держу, и они соответствуют!

Я переместил частный член в синхронизированный getter / setter, добавив журнал изменений, что не улавливает проблему.

Вот псевдокод моего setter / getter и периодический статус + тревожный журнал:

public class Manager {
    private volatile byte[] readerID = null;    public synchronized void setReaderID(byte[] readerID) {
        this.readerID = readerID;
        logger.debug("readerID = {}", StringUtilities.binaryToAscii(this.readerID));
    }    public synchronized byte[] getReaderID() {
        if (this.readerID == null)
            return null;
        return Arrays.copyOf(this.readerID, this.readerID.length);
    }    /* Called every second */
    public void periodicStatus() {
        logger.debug("readerID = {}", StringUtilities.binaryToAscii(getReaderID()));
    }
}13:53:46,103|ad-5|INFO |Manager|readerUpdateFinish(): Received firmware install finish for reader 000189D0 at slot 0
13:53:46,103|ad-5|DEBUG|Manager|setReaderID(): readerID = 000189D0
13:53:46,103|ad-5|DEBUG|Manager|readerUpdateFinish(): triggered reader firmware timer, 1526986426103, 000189D0
13:53:46,408|ad-5|DEBUG|Manager|periodicStatus(): readerID = E69EAD03 // <- where's the setter???
13:53:50,030|ad-5|INFO |Manager|readerStatus(): Received status information for reader 000189D0 at slot 0
13:53:50,031|ad-5|DEBUG|Manager|setReaderID(): readerID = null
13:53:50,031|ad-5|DEBUG|Manager|readerStatus(): timer cleared, null

Любые идеи?

1 ответ

Rami Rosenbaum ответил: 03 мая 2018 в 08:06

Как указал Прогман, идентификатор readerID передается по ссылке. Он поступает из транспортного уровня, который хранится там как член-экземпляр, и обновляется следующим входящим сообщением с новым идентификатором, который отображается.