我正在尝试使用名为 EsperTech 的依赖项以本机模式构建我的 quarkus 应用程序,并且有一段特定的代码片段,经过无数个小时的调试后,我发现这给我带来了问题。基本上它处理一些字节被写入缓冲区并在其之后读取(这会导致以下错误)。
java.io.InvalidClassException: my.package.CustomConfigurationClass; no valid constructor
代码片段是这个(我改编为kotlin代码):
import com.espertech.esper.common.internal.util.SimpleByteArrayOutputStream
import com.espertech.esper.common.internal.util.ObjectInputStreamWithTCCL
import my.package.CustomConfigurationClass
import java.io.IOException
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
fun <T> copy(configObj: T): T {
val fbos = SimpleByteArrayOutputStream()
val outStream = ObjectOutputStream(fbos)
try {
outStream.writeObject(orig)
outStream.flush()
} finally {
outStream.close()
}
// ...
val inStream: ObjectInputStream = ObjectInputStreamWithTCCL(fbos.inputStream)
inStream.readObject() // Where the error happens
}
正如您所看到的,它完全在
readObject
函数中抛出,我已经检查过,是的,在尝试读取缓冲区之前已正确保存缓冲区。
正如错误所示,我尝试让我的类为本机模式做好准备,如下所示(在执行请求/响应 api 时适用于序列化,但在使用 java.io 库时不适用于这种情况)。
@RegisterForReflection
@kotlinx.serialization.Serializable
data class CustomConfigurationClass(
val name: String = "CustomConfigurationClass",
) : Serializable {
constructor() : this("CustomConfigurationClass") // I know I do not need this but I try it to ensure either way
}
还有其他方法可以使用
java.io
std 库处理此类序列化问题吗?
顺便说一句,我假设这是问题所在,但也可能是其他问题。
我尝试使用以下方法将这段代码与 java.io 库一起从本机构建中排除:
gradle build -x test -Dquarkus.package.type=native -Dquarkus.native.additional-build-args="--initialize-at-run-time=java.io\\,<esper_package>\\,etc"
但也没有运气。
解决了!
我使用了此处发布的相同解决方案:Quarkus hibernate Exception in native mode
我的
serialization-config.json
文件:
[
{"name":"java.io.ObjectInputStream"},
{"name":"java.io.ObjectOutputStream"},
{"name":"java.lang.String"},
{"name":"my.custom.package.config.ConfigurationCustom"},
... Other esper library package
]
每次重新执行本机构建时,我都会收到此错误消息:
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: SerializationConstructorAccessor class not found for declaringClass: com.espertech.esper.common.client.configuration.compiler.ConfigurationCompilerLanguage (targetConstructorClass: java.lang.Object). Usually adding com.espertech.esper.common.client.configuration.compiler.ConfigurationCompilerLanguage to serialization-config.json fixes the problem.
只需按照建议(向
serialization-config.json
添加更多包)我就能够成功执行。
唯一的缺点是每次构建只是为了在我的 json 文件中添加一个类/包,但这就是我现在设法解决的方法。