我正在 Groovy/Grails 中开发一个应用程序,它应该处理来自旧数据库的一些数据。已处理表之一中的一列具有 BLOB 类型,并且它存储使用 writeObject() 方法在 Java 中序列化的对象。 我可以读取域对象的实例,但是当我尝试使用以下代码反序列化该字段时:
def stream = new ObjectInputStream(new ByteArrayInputStream(instance.body))
TargetRequest request = (TargetRequest)stream.readObject()
stream.close()
它在第二行(readObject)上吹动
block 引用>ERROR errors.GrailsExceptionResolver - ClassNotFoundException occurred when processing request
TargetRequest 是我的旧版 Java 对象的 Groovy 副本,但该消息要求原始(旧版)类。我将相应的 JAR 文件作为运行时依赖项添加到我的项目中,但仍然找不到它。 这是堆栈跟踪:
Line | Method ->> 366 | run in java.net.URLClassLoader$1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 355 | run in '' | 354 | findClass . . . . in java.net.URLClassLoader | 425 | loadClass in java.lang.ClassLoader | 358 | loadClass . . . . in '' | 270 | forName in java.lang.Class | 625 | resolveClass . . . in java.io.ObjectInputStream | 1612 | readNonProxyDesc in '' | 1517 | readClassDesc . . in '' | 1771 | readOrdinaryObject in '' | 1350 | readObject0 . . . in '' | 370 | readObject in '' | 33 | $tt__doFormat . . in com.abc.def.xyz.DataFormattingService | 24 | $tt__formatData in '' | 12 | index . . . . . . in com.abc.def.xyz.DataFormattingServiceController | 198 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter | 63 | doFilter . . . . . in grails.plugin.cache.web.filter.AbstractFilter | 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor | 615 | run . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker ^ 744 | run in java.lang.Thread
该堆栈跟踪中的第 33 行指向上述代码行。 调查问题时,我在 readObject 调用之前在代码中添加了以下行
TargetRequest targetRequest = Class.forName('com.ijk.mln.domain.TargetRequest').newInstance()
类已成功加载,对象已实例化。为什么它无法在下一行加载完全相同的类,这超出了我的范围。我不知道该怎么做。只是没有更多的想法。
如果有人能帮助我解决这个问题,我将非常感激。
最佳答案
尝试一下:
new ByteArrayInputStream(instance.body).withObjectInputStream(getClass().classLoader) { is ->
TargetRequest targetRequest = (TargetRequest)is.readObject()
}
这样类加载器就会知道序列化的类类型。
<小时/>根据我对用户评论的理解添加其他信息:
Grails 使用自定义类加载器。子类加载器可以找到父类加载器中加载的类,但反之则不行。因此,一旦我们提供了一个类加载器,它就会使用提供的类加载器而不是默认的。
例如在应用程序中使用以下代码片段:
def cl = getClass().classLoader
log.debug "Child ClassLoader ==> ${cl}"
while(cl.parent){
log.debug "==> ${cl.parent}"
cl = cl.parent
}
将产生如下类似的输出:
Child ClassLoader ==> java.net.URLClassLoader@162ffbfc
==> org.grails.launcher.rootloader.RootLoader@12f483b4
==> sun.misc.Launcher$AppClassLoader@6fafc4c2
==> sun.misc.Launcher$ExtClassLoader@7c9ed5d6
关于java - 在 groovy 中反序列化 java 对象时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27306176/