我有一个使用mvn3构建,测试和部署(作为jar)的scala库。代码在这些构建和测试条件下正常工作。我目前正试图在客户端项目使用sbt并发现sbt和mvn3之间存在差异的客户端项目中使用此库。特别是,在sbt控制台下,反序列化堆栈无法访问包含项目依赖项的类路径。这会导致在我的库中的代码路径中调用异常。
java.lang.ClassNotFoundException: com.biosimilarity.lift.model.store.PersistedMonadicKVDBMongoNodeScope$PersistenceScope$BasePersistedMonadicKVDBNode$$anonfun$mget$2$$anonfun$apply$40$$anonfun$apply$41$$anonfun$apply$42
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:249)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1591)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
at scala.collection.immutable.$colon$colon.readObject(List.scala:362)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:979)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1873)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1777)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1970)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1895)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1777)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
at com.biosimilarity.lift.model.store.PersistedMonadicKVDBMongoNodeScope$PersistenceScope$MongoDBManifest.asCacheK(PersistedMonadicKVDBMongoNode.scala:445)
...
我的代码捕获并序列化一个延续(对于一个长寿命的状态机)并反序列化延续以推进状态机。在sbt控制台下,当对序列化进行反序列化时,由对readObject的递归调用触发的resolveClass无法找到该类(即使该类位于与项目依赖项关联的jar中)。这似乎是因为通过反序列化代码路径访问的类加载器无法访问具有项目依赖关系的类路径。
我尝试通过定义自己的ObjectInputStream并覆盖resolveClass来解决问题。
class DefensiveObjectInputStream( in : InputStream ) extends ObjectInputStream( in ) {
override def resolveClass( desc : ObjectStreamClass ) : Class[_] = {
try {
val currentTccl = Thread.currentThread().getContextClassLoader()
currentTccl.loadClass( desc.getName() )
} catch {
case e : Throwable => super.resolveClass(desc);
}
}
}
但是,这不起作用,因为问题是在递归调用中触发的,并且在递归调用中访问的类加载器无法访问项目的类路径。我做了一个开源的复制here。这几乎是一个空的sbt项目,只是调用我的库来说明问题。对于基于mvn3的等效项目,有一个pom.xml文件。它就像一个魅力。任何帮助将不胜感激。