ObjectInputStream.readObject() java.io.InvalidClassException: java.util.HashMap; локальный класс несовместим: поток classdesc с graalVM

  • Укажите подробную информацию о своей цели:

Используйте return (Map<?, ?>) objectInputStream.readObject();, чтобы получить карту без сбоев в собственном образе graalVM.

  • Покажите код:

Код на самом деле очень простой. Всего два файла, которые можно скопировать и вставить в вашу среду для воспроизведения.

private static Map<?, ?> getNormalizedMap(String encoded) {
        try (var objectInputStream = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(encoded)))) {
            return (Map<?, ?>) objectInputStream.readObject(); // issue here !
        } catch (IOException | ClassNotFoundException | IllegalArgumentException e) {
            LOGGER.error("encoded = {}", encoded, e);
            return Map.of();
        }
    }

полный файл:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Base64;
import java.util.Map;

@RestController
@SpringBootApplication
public class GraalissueApplication {

    public static void main(String[] args) {
        SpringApplication.run(GraalissueApplication.class, args);
    }

    @GetMapping("/graalissue")
    public String index() {
        String base64encoded = "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 = ";
        Map map = getNormalizedMap(base64encoded);
        return "It should be 41 here => " + map.size();
    }

    private static Map<?, ?> getNormalizedMap(final String encoded) {
        try (var objectInputStream = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(encoded)))) {
            return (Map<?, ?>) objectInputStream.readObject();
        } catch (IOException | ClassNotFoundException | IllegalArgumentException e) {
            e.printStackTrace();
            return Map.of();
        }
    }

}

пом:

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>graalissue</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>graalissue</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>22</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <image>
                        <env>
                            <BP_JVM_VERSION>22</BP_JVM_VERSION>
                            <BP_NATIVE_IMAGE_BUILD_ARGUMENTS>-H:-AddAllFileSystemProviders</BP_NATIVE_IMAGE_BUILD_ARGUMENTS>
                        </env>
                    </image>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

  • Опишите ожидаемые результаты:

return (Map<?, ?>) objectInputStream.readObject(); вернет правильную карту. В случае этой проблемы ожидаемый результат должен быть

  1. просто запустите mvn clean install и запустите jar
  2. сделайте http-запрос, curl http://localhost:8080/graalissue
  3. ожидаемый результат: «Здесь должно быть 41 => 41»

Я ожидал увидеть «Здесь должно быть 41 => 41» как для собственного, так и для неродного изображения.

  • Опишите фактические результаты:
  1. запустите mvn -Pnative spring-boot:build-image, это создаст собственный образ graalvm
  2. run docker tag docker.io/library/graalissue:0.0.1-SNAPSHOT graalissue:latest
  3. docker run -p 8080:8080 graalissue:latest
  4. curl http://localhost:8080/graalissue Выходной размер будет 0.
  • Включите все сообщения об ошибках:

Это не удается ни с одним, ни с другим

  1. прошу добавить java.util.Collections$UnmodifiableMap к serialization-config.json
  2. если я добавлю java.util.Collections$UnmodifiableMap к serialization-config.json (в правильности чего я даже не уверен), я получу java.io.InvalidClassException: java.util.HashMap; local class incompatible: stream classdesc

Если я ничего не добавляю в serialization-config.json, произойдет ошибка, и трассировка стека попросит меня добавить java.util.Collections$UnmodifiableMap в serialization-config.json.

Если я добавлю его, я получу следующую трассировку стека:

java.io.InvalidClassException: java.util.HashMap; local class incompatible: stream classdesc serialVersionUID = 362498820763181265, local class serialVersionUID = -3563561681480877083
        at [email protected]/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:598)
        at [email protected]/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2063)
        at [email protected]/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1912)
        at [email protected]/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2237)
        at [email protected]/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1747)
        at [email protected]/java.io.ObjectInputStream$FieldValues.<init>(ObjectInputStream.java:2603)
        at [email protected]/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2454)
        at [email protected]/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2269)
        at [email protected]/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1747)
        at [email protected]/java.io.ObjectInputStream.readObject(ObjectInputStream.java:525)
        at [email protected]/java.io.ObjectInputStream.readObject(ObjectInputStream.java:483)
  • Вопрос:

Как обойти эту проблему?

Как правильно return (Map<?, ?>) objectInputStream.readObject(); использовать собственный образ graalVM, поскольку код в неродном образе вообще не имеет проблем?

Очевидно, вы не можете, потому что, очевидно, Graal дал ему другой serialVersionUID, чем JDK, как вы можете видеть в сообщении об исключении. Значение JDK не изменилось с версии 1.2 (конечно). Похоже, вам придется как-то разворачивать собственную сериализацию.

user207421 16.05.2024 01:06

Проголосуйте за, хотя это ясный ответ, я очень надеюсь, что есть способ

PatPanda 16.05.2024 02:38

Вам придется сериализовать все ключи и их значения отдельно и восстановить карту на получателе. Вините Грааля, это их вина, и ничья больше.

user207421 16.05.2024 07:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
155
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Предполагая, что не совпадает только серийныйVersionUID, но структура в остальном одинакова, вы можете использовать входной поток пользовательского объекта, заменяя дескриптор класса:

class FixingObjectInputStream extends ObjectInputStream {
    public FixingObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass streamDescriptor = super.readClassDescriptor();
        return streamDescriptor.getName().equals("java.util.HashMap")?
            ObjectStreamClass.lookup(HashMap.class): // use runtime version
            streamDescriptor;
    }
}

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

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

// matches the serialized format of OpenJDK’s and compatible HashMaps
static class StreamMap<K, V> implements Serializable {
    transient Object[] data;
    int threshold;
    float loadFactor;

    private void writeObject(java.io.ObjectOutputStream out) throws IOException {}

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.readFields();
        in.readInt();
        int size = in.readInt();
        data = new Object[size * 2];
        for(int counter = 0, index = 0; counter < size; counter++) {
          data[index++] = in.readObject();
          data[index++] = in.readObject();
        }
    }

    Object readResolve() throws ObjectStreamException {
        HashMap<Object,Object> actualResult = new HashMap<>();
        for(int index = 0; index < data.length; ) {
            actualResult.put(data[index++], data[index++]);
        }
        System.out.println("StreamMap.readResolve(): constructed actual map");
        return actualResult;
    }
}

Затем адаптируйте FixingObjectInputStream:

class FixingObjectInputStream extends ObjectInputStream {
    public FixingObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass streamDescriptor = super.readClassDescriptor();
        return streamDescriptor.getName().equals("java.util.HashMap")?
            ObjectStreamClass.lookup(StreamMap.class): // use replacement
            streamDescriptor;
    }
}

…и мы можем прочитать карту, даже если исполняемая версия HashMap реализована совершенно по-другому:

String encoded = "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 = ";

try(var objectInputStream = new FixingObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(encoded)))) {
    var map = (Map<?, ?>) objectInputStream.readObject();
    System.out.println(map.size() == 41);
    map.forEach((k,v) -> System.out.println(k + "-> " + v));
}
StreamMap.readResolve(): constructed actual map
true
stage-feedbacks-gfeclient-*-> [user.uid, user.id, device.id, deviceId, userId, user.externalId]
stage-feedbacks-gfe_nvbackend-*-> [user.uid, user.id, device.id, deviceId, userId, user.externalId]
…

Другие вопросы по теме