Java: загрузить объект, сохраненный на жесткий диск, после рефакторинга => исключение "class not found": / - PullRequest
5 голосов
/ 12 мая 2010

Я разрабатываю приложение в Java, которое регулярно сохраняет объекты на жесткий диск, используя этот простой метод:

public void save(String filename)
{
    try
    {
        FileOutputStream fos = new FileOutputStream(filename);
        GZIPOutputStream gzos = new GZIPOutputStream(fos);
        ObjectOutputStream out = new ObjectOutputStream(gzos);
        out.writeObject(this);
        out.flush();
        out.close();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

}

Объект является экземпляром класса sebbot.learning.DirectPolicySearch.

Проблема в том, что после некоторого рефакторинга учебный пакет был переименован в «ballcapture». Теперь, когда я пытаюсь загрузить сохраненный файл, я получаю следующее исключение:

java.lang.ClassNotFoundException: sebbot.learning.DirectPolicySearch

Метод загрузки файла:

public static synchronized DirectPolicySearch load(String filename)
{
    DirectPolicySearch dps = null;
    try
    {
        FileInputStream fis = new FileInputStream(filename);
        GZIPInputStream gzis = new GZIPInputStream(fis);
        ObjectInputStream in = new ObjectInputStream(gzis);
        dps = (DirectPolicySearch) in.readObject();
        in.close();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    System.out.println(dps);

    return dps;
}

Может кто-нибудь помочь мне с этим? Большое спасибо.

Ответы [ 4 ]

7 голосов
/ 12 мая 2010

Изменения имени класса (включая изменения имени пакета) являются гарантированным способом сломать механизм сериализации; он просто не предназначен для работы с классами, которые меняют имена.

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

Если вы хотите быть в безопасности от такого рода хлопот, рассмотрите возможность использования более надежного и гибкого метода сериализации, например XStream .

2 голосов
/ 12 мая 2010

Ваш пример демонстрирует, почему сериализация не подходит для длительного хранения данных: у вас нет (реального) контроля над форматом файла, а сериализованные файлы очень тесно связаны с вашим исходным кодом - если вы измените свой исходный код, вы больше не можете читать ранее сериализованные файлы.

Приложения, где сериализация полезна, когда RMI используется для отправки объектов по сетевому соединению или для кратковременного временного хранения данных (например, для кэша на диске).

Для долгосрочного хранения данных используйте что-то другое, например XML, как предлагает Майкл, или какой-то другой (стандартный) формат файла.

0 голосов
/ 30 апреля 2012

Я написал небольшой инструмент для изменения имени / пути класса в сериализованном потоке / файле. См. Код и его использование здесь: Изменить путь / имя класса сериализованного объекта Java после рефакторинга

0 голосов
/ 12 января 2011

В настоящее время я сталкиваюсь с подобной проблемой, даже в моем случае все остается таким же, кроме имени пакета. Я думаю о том, чтобы прочитать сериализованные данные в виде потока и заменить все вхождения com.oldPackage.class на com.newPackage.class. Не уверен, что это будет работать, любые комментарии будут полезны здесь.

...