有问题在groovy中反序列化java对象

时间:2014-12-04 23:32:01

标签: 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     处理请求时发生

  

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()

该类已成功加载并且对象已实例化。为什么它不能在下一行加载同一个类是超出我的。我没办法。只是没有更多的想法。

如果有人可以帮我解决这个问题,我会非常感激。

1 个答案:

答案 0 :(得分:2)

尝试一下:

new ByteArrayInputStream(instance.body).withObjectInputStream(getClass().classLoader) { is ->
    TargetRequest targetRequest = (TargetRequest)is.readObject()
}

这样,类加载器将知道序列化的类类型。


根据我对用户评论的理解添加其他信息:

Grails使用自定义类加载器。子类classLoader可以找到父classLoader中加载的类,但反之不然。因此,一旦我们提供了一个classLoader,它就会使用提供的一个而不是默认的。

例如,在应用程序中使用以下代码片段:

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