Анализатор обнаружил ситуацию, когда объект однажды уже записанный в поток, спустя какое-то время записывается в него снова с измененным состоянием. Из-за нюансов 'java.io.ObjectOuputStream' это приведет к тому, что измененное состояние сериализуемого объекта будет проигнорировано в пользу исходного.
Класс 'java.io.ObjectOuputStream', который используется для сериализации, кэширует записываемые объекты. Это означает, что один и тот же объект не будет сериализоваться дважды. Один раз класс сериализует объект, а во второй раз просто запишет в поток ссылку на тот же самый первый объект. В этом и кроется подводный камень. Если мы сериализуем объект, изменим его, а после снова сериализуем, то 'java.io.ObjectOuputStream' об изменениях объекта ничего не узнает, поэтому сочтет объект тем же самым, который был сериализован ранее.
Рассмотрим некорректный синтетический пример, в котором будет проигнорировано изменение состояния объекта при сериализации:
ObjectOutputStream out = new ObjectOutputStream(....); SerializedObject obj = new SerializedObject(); obj.state = 100; out.writeObject(obj); // сохраняет объект с состоянием = 100 obj.state = 200; out.writeObject(obj); // сохраняет объект с состоянием = 100 (а ожидалось 200) out.close();
Чтобы избежать подобного поведения, есть два способа.
Самым простым и надежным решением является создание нового экземпляра этого объекта с необходимым состоянием. Рассмотрим пример:
ObjectOutputStream out = new ObjectOutputStream(....); SerializedObject obj = new SerializedObject(); obj.state = 100; out.writeObject(obj); obj = new SerializedObject(); obj.state = 200; out.writeObject(obj); out.close();
Следующий способ менее тривиален. Он заключается в использовании метода 'reset' класса 'java.io.ObjectOuputStream'. Использовать данный способ рекомендуется только тогда, когда вы хорошо понимаете, что делаете и зачем, так как 'reset' обнулит информацию обо всех объектах, ранее записанных в поток. Рассмотрим пример:
ObjectOutputStream out = new ObjectOutputStream(....); SerializedObject obj = new SerializedObject(); obj.state = 100; out.writeObject(obj); out.reset(); obj.state = 200; out.writeObject(obj); out.close();