首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >sbt运行IMain,play会出错

sbt运行IMain,play会出错
EN

Stack Overflow用户
提问于 2014-03-11 15:37:43
回答 2查看 166关注 0票数 0

我已经构建了一个litte对象,它可以动态地解释scala代码并从中捕获一个值。

代码语言:javascript
运行
复制
object Interpreter {
  import scala.tools.nsc._
  import scala.tools.nsc.interpreter._

  class Dummy

  val settings = new Settings
  settings.usejavacp.value = false
  settings.embeddedDefaults[Dummy]  // to make imain useable with sbt.

  val imain = new IMain(settings)

  def run(code: String, returnId: String) = {
    this.imain.beQuietDuring{
      this.imain.interpret(code)
    }
    val ret = this.imain.valueOfTerm(returnId)
    this.imain.reset()
    ret
  }
}

object Main {
  def main(args: Array[String]) {
    println(Interpreter.run("val x = 1", "x"))
  }
}

在纯sbt环境中或由scala解释器调用,此代码工作良好!但是,如果我在一个简单的play (Version2.2.2)应用程序中运行它,它将在val ret = this.imain.valueOfTerm(returnId)上获得一个空指针。

play 还使用了修改的 sbt,因此它可能会工作。如果这段代码不再工作,play 会做什么呢?如何让这段代码在play**?** 中工作

备注

那是用过的build.sbt

代码语言:javascript
运行
复制
name := "Test"

version := "1.0"

scalaVersion := "2.10.3"

libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value

或者,我尝试了这个实现,但它也解决不了这个问题:

代码语言:javascript
运行
复制
object Interpreter2 {
  import scala.tools.nsc._
  import scala.tools.nsc.interpreter._
  import play.api._
  import play.api.Play.current 

  val settings: Settings = {
    lazy val urls = java.lang.Thread.currentThread.getContextClassLoader match {
      case cl: java.net.URLClassLoader => cl.getURLs.toList
      case _ => sys.error("classloader is not a URLClassLoader")
    }

    lazy val classpath = urls map {_.toString}

    val tmp = new Settings()
    tmp.bootclasspath.value = classpath.distinct mkString java.io.File.pathSeparator
    tmp
  }

  val imain = new IMain(settings)

  def run(code: String, returnId: String) = {
    this.imain.beQuietDuring {
      this.imain.interpret(code)
    }
    val ret = this.imain.valueOfTerm(returnId)
    this.imain.reset()
    ret
  }
}

我发现了进行第二个实现的有用链接:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-21 09:58:31

这是因为play使用了来自sbt的“叉入运行”特性。此特性启动一个新JVM,这将导致出现此故障:

代码语言:javascript
运行
复制
[info] Failed to initialize compiler: object scala.runtime in compiler mirror not found.
[info] ** Note that as of 2.8 scala does not assume use of the java classpath.
[info] ** For the old behavior pass -usejavacp to scala, or if using a Settings
[info] ** object programatically, settings.usejavacp.value = true.

请参阅:http://www.scala-sbt.org/release/docs/Detailed-Topics/Forking

票数 0
EN

Stack Overflow用户

发布于 2014-05-29 03:23:56

在这个问题上花了几个小时之后,我想出了一个解决方案。它在SBT内部和外部都能工作。它还可以在各种托管环境(如OSGi)中工作:

代码语言:javascript
运行
复制
private def getClasspathUrls(classLoader: ClassLoader, acc: List[URL]): List[URL] = {
    classLoader match {
      case null                        => acc
      case cl: java.net.URLClassLoader => getClasspathUrls(classLoader.getParent, acc ++ cl.getURLs.toList)
      case c                           => LOGGER.error("classloader is not a URLClassLoader and will be skipped. ClassLoader type that was skipped is " + c.getClass)
                                          getClasspathUrls(classLoader.getParent, acc)
    }
}
val classpathUrls = getClasspathUrls(this.getClass.getClassLoader, List())
val classpathElements = classpathUrls map {url => url.toURI.getPath}
val classpath = classpathElements mkString java.io.File.pathSeparator
val settings = new Settings
settings.bootclasspath.value = classpath
val imain = new IMain(settings)
// use imain to interpret code. It should be able to access all your application classes as well as dependent libraries. 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22330243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档