2011-08-29 63 views
2

當我 「SBT運行」 下面的代碼,斯卡拉SBT:可能的錯誤?

package com.example 

import java.io.ObjectInputStream 
import java.io.ObjectOutputStream 
import java.io.FileInputStream 
import java.io.FileOutputStream 

object SimpleFailure extends App { 
    case class MyClass(a: String, b: Int, c: Double) 

    def WriteObjectToFile[A](obj: A, filename: String) { 
    val output = new ObjectOutputStream(new FileOutputStream(filename, false)) 
    output.writeObject(obj) 
    } 

    def ReadObjectFromFile[A](filename: String)(implicit m: Manifest[A]): A = { 
    val obj = new ObjectInputStream(new FileInputStream(filename)) readObject 

    obj match { 
     case a if m.erasure.isInstance(a) => a.asInstanceOf[A] 
     case _ => { sys.error("Type not what was expected when reading from file") } 
    } 
    } 

    val orig = MyClass("asdf", 42, 2.71) 
    val filename = "%s/delete_me.spckl".format(System.getProperty("user.home")) 

    WriteObjectToFile(List(orig), filename) 

    val loaded = try { 
    ReadObjectFromFile[List[MyClass]](filename) 
    } catch { case e => e.printStackTrace; throw e } 

    println(loaded(0)) 
} 

我得到以下異常:

java.lang.ClassNotFoundException: com.example.SimpleFailure$MyClass 

不過,我可以用Scala的插件在Eclipse中運行代碼的罰款。這是一個SBT錯誤嗎?有趣的是,只有在將MyClass包裝到List中時纔會出現問題(請參閱WriteObjectToFile調用中的「orig」如何包裝在List中)。如果我不包裝在列表中,一切正常。

+1

更新:將「fork in run:= true」添加到build.sbt是一種解決方法:https://github.com/harrah/xsbt/issues/89 – emchristiansen

回答

2

我也能夠使用sbt 0.10.1和scalaVersion := "2.9.0-1"重現這一點。你可能應該在github上報告它,或者把它放在郵件列表中。

+2

感謝您的重製。我已經創建了一個錯誤報告:https://github.com/harrah/xsbt/issues/163 – emchristiansen

4

this在build.sbt或項目文件:

fork in run := true 
+0

謝謝,這是行不通的。我也已經添加了,作爲對原帖的評論;) – emchristiansen

+0

是的,那是我評論Github的XSBT問題。感謝upvote :-) – opyate

2

這個問題似乎是與SBT時加載你的代碼,被使用的類加載器。 ObjectInputStream描述了它是默認的類加載器分辨率,它使堆棧走向。通常情況下,這最終會發現與程序相關的加載器,但在這種情況下,它最終會使用錯誤的加載器。

我能夠通過在我的代碼中包含以下類,並直接使用它來代替ObjectInputStream來解決此問題。

package engine; 

import java.io.InputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectStreamClass; 

class LocalInputStream extends ObjectInputStream { 
    LocalInputStream(InputStream in) throws IOException { 
     super(in); 
    } 

    @Override 
    protected Class<?> resolveClass(ObjectStreamClass desc) 
     throws ClassNotFoundException 
    { 
     return Class.forName(desc.getName(), false, 
       this.getClass().getClassLoader()); 
    } 
} 

這覆蓋了resolveClass方法,並且總是使用與此特定類關聯的方法。只要這個類是你的應用程序的一部分,這應該工作。

順便說一下,這比運行fork要快,但它也適用於Play框架,它目前不支持在dev模式下分叉。