java - 在 groovy 中反序列化 java 对象时遇到问题

标签 java grails groovy deserialization

我正在 Groovy/Grails 中开发一个应用程序,它应该处理来自旧数据库的一些数据。已处理表之一中的一列具有 BLOB 类型,并且它存储使用 writeObject() 方法在 Java 中序列化的对象。 我可以读取域对象的实例,但是当我尝试使用以下代码反序列化该字段时:

    def stream = new ObjectInputStream(new ByteArrayInputStream(instance.body))
    TargetRequest request = (TargetRequest)stream.readObject()
    stream.close()

它在第二行(readObject)上吹动

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/

相关文章:

java - 字符串的 Gson 数组到 JsonArray

java - 在 Maven 中添加外部 JAR 会导致 NoClassDefFoundError

java - 使用 svnkit 通过 https 从 SVN 读取文件

class - grails域类后加载将值保存在数据库中

java - build.gradle 中的方法返回类型

java - java RMI中本地方法调用是否等待远程返回值?

json - 使用grails-json-rest-api-plugin时获取请求失败

eclipse - GGTS-在工作空间首选项中未配置Grails安装

groovy - 如何从管道 (jenkinsfile) 中使用 Jenkins Copy Artifacts 插件?

groovy - 如何消除编译任务期间的随机常规错误