我正在使用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()
该类已成功加载并且对象已实例化。为什么它不能在下一行加载同一个类是超出我的。我没办法。只是没有更多的想法。
如果有人可以帮我解决这个问题,我会非常感激。
答案 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