Используйте 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();
вернет правильную карту. В случае этой проблемы ожидаемый результат должен быть
curl http://localhost:8080/graalissue
Я ожидал увидеть «Здесь должно быть 41 => 41» как для собственного, так и для неродного изображения.
mvn -Pnative spring-boot:build-image
, это создаст собственный образ graalvmrun docker tag docker.io/library/graalissue:0.0.1-SNAPSHOT graalissue:latest
docker run -p 8080:8080 graalissue:latest
curl http://localhost:8080/graalissue
Выходной размер будет 0.Это не удается ни с одним, ни с другим
java.util.Collections$UnmodifiableMap
к serialization-config.json
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, поскольку код в неродном образе вообще не имеет проблем?
Проголосуйте за, хотя это ясный ответ, я очень надеюсь, что есть способ
Вам придется сериализовать все ключи и их значения отдельно и восстановить карту на получателе. Вините Грааля, это их вина, и ничья больше.
Предполагая, что не совпадает только серийный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]
…
Очевидно, вы не можете, потому что, очевидно, Graal дал ему другой
serialVersionUID
, чем JDK, как вы можете видеть в сообщении об исключении. Значение JDK не изменилось с версии 1.2 (конечно). Похоже, вам придется как-то разворачивать собственную сериализацию.