我开发了一个小型的应用程序,存储来自设备的数据。我选择以Json格式存储数据,数据的序列化解序列化工作得很好,即使它涉及到我创建的一些自定义类型......但只有我在IDE(Eclipse)中工作。
不过当我导出一个可运行的jar时,数据的反序列化遇到了某种问题,因为软件总是抛出这个异常。
Caused by: java.lang.UnsupportedOperationException: Cannot allocate class LocalDateTime
at com.google.gson.internal.UnsafeAllocator$4.newInstance(UnsafeAllocator.java:104)
at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:225)
... 88 common frames omitted
我想我遇到的问题是自定义类型,而不是内置类型。这时,我发现了两件事。
在这一点上,我想我可以简单的为每个引起问题的数据类型添加一个反序列器,但是我想知道 为什么在使用完整的JRE时不会发生这个问题,为什么在使用较小的JRE时就会发生这个问题即使所有需要的模块都包含在内。也许值得一提的是,我没有在保存数据的Gson对象中添加自定义序列化器,而是按照GSON的默认值进行序列化。
LocalDateTime
deserializer。
@Override
public LocalDateTime deserialize(JsonElement json, java.lang.reflect.Type type,
JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject joDate = json.getAsJsonObject().get("date").getAsJsonObject();
JsonObject joTime = json.getAsJsonObject().get("time").getAsJsonObject();
//JSON example: {"date":{"year":2019,"month":1,"day":9},"time":{"hour":6,"minute":14,"second":1,"nano":0}
return LocalDateTime.of(joDate.get("year").getAsInt(),
joDate.get("month").getAsInt(),
joDate.get("day").getAsInt(),
joTime.get("hour").getAsInt(),
joTime.get("minute").getAsInt(),
joTime.get("second").getAsInt(),
joTime.get("nano").getAsInt());
}
}
Jdeps.deps模块列表。
com.google.gson
java.base
javafx.base
javafx.controls
javafx.fxml
javafx.graphics
org.slf4j
EDIT:在我收到答案后,我开了一个问题 此处
你需要一个运行时映像(例如完整的JDK或用jlink构建的东西),其中包括模块 jdk.unsupported.
GSON希望在不调用任何构造函数的情况下创建反序列化的类的实例(所以在GSON没有说明的情况下,没有任何东西被初始化)。这通常是不能做到的,但是 sun.misc.Unsafe
提供了一种方法来实现这一目标,方法是 allocateInstance
. 为此,GSON需要一个实例的 sun.misc.Unsafe
. 调用栈中最上面的一帧来自于 UnsafeAllocator
,它使用 巧取豪夺 Unsafe
.
问题是: sun.misc.Unsafe
是在模块 jdk.unsupported在完整的JDK中存在,但你通常不会在运行时映像中找到。
当使用jlink创建运行时映像时,请确保包含以下选项 --add-modules jdk.unsupported
你就可以走了。
可以说,GSON应该宣布一个 可选依赖性 关于 jdk.unsupported 与 requires static
.