【问题标题】:Using forked JVM when using runner in SBT在 SBT 中使用运行器时使用分叉的 JVM
【发布时间】:2015-11-05 01:01:21
【问题描述】:

我的目标是在从 JAR 中加载资源并在 SBT 中从 JAR 运行应用程序时避免 FileNotFound 异常。

我有以下任务:

val generateSource = TaskKey[Unit]("generateSource")
val generateSourceImpl : Def.Initialize[Task[Unit]] = {
  Def.task {
    val localGeneratorJar = file(s"${baseDirectory.value.getParentFile.toString}/generator/repo/.sbt/generator.jar")
    if (!localGeneratorJar.exists()) {
      sys.error(s"Generator not found, please execute 'sbt publishLocal' in 'generator' project first.")
    }
    val r = (runner in Compile).value
    val opts = Seq( /*  options here */ )
    toError(r.run(“com.example.AllMightyCompiler", Seq(localGeneratorJar), opts, streams.value.log))
  }
}

问题发生在 AllMightyCompiler 加载时,例如来自‘localGeneratorJar’本身和 JAR 的 XSD 模式在 sbt 任务的运行之间被修改。 典型的工作流程是:

$ sbt
> generateSource
# all good, but
# when in meantime ‘generator.jar is modified’ task invocation will be
> generateSource 
root > generateSource
[info] Running AllMightyCompiler —opts=dummy
com.example.GeneratorException: org.xml.sax.SAXParseException; schema_reference.4: Failed to read schema document 'jar:file:/Users/Me/Development/Work/generator/repo/.sbt/generator.jar!/module.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
    at com.example.ModuleLoader.<init>(ModuleLoader.java:127)
    at com.example.AllMightyCompiler.loadModel(Compiler.java:394)
    at com.example.AllMightyCompiler.generateImpl(Compiler.java:264)
    at com.example.AllMightyCompiler.generate(Compiler.java:144)
    at com.example.AllMightyCompiler.main(Compiler.java:134)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at sbt.Run.invokeMain(Run.scala:72)
    at sbt.Run.run0(Run.scala:65)
    at sbt.Run.sbt$Run$$execute$1(Run.scala:54)
    at sbt.Run$$anonfun$run$1.apply$mcV$sp(Run.scala:58)
    at sbt.Run$$anonfun$run$1.apply(Run.scala:58)
    at sbt.Run$$anonfun$run$1.apply(Run.scala:58)
    at sbt.Logger$$anon$4.apply(Logger.scala:90)
    at sbt.TrapExit$App.run(TrapExit.scala:244)
    at java.lang.Thread.run(Thread.java:744)
Caused by: org.xml.sax.SAXParseException; schema_reference.4: Failed to read schema document 'jar:file:/Users/Me/Development/Work/generator/repo/.sbt/generator.jar!/module.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:347)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4166)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4149)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchemaDocument1(XSDHandler.java:2479)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchemaDocument(XSDHandler.java:2187)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:573)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:616)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:574)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:540)
    at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:255)
    at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:638)
    at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:670)
    at n4.generator.util.ModuleLoader.<init>(ModuleLoader.java:121)
    ... 17 more

据我所知,有两种可能的解决方案:

  • 直接在 com.example.ModuleLoader 中禁用 JAR URL 缓存
  • 不知何故,我的 sbt 任务“generateSources”中的 fork runner

选项 1 可以通过以下方式完成:

new URLConnection(schemaURL) {
    @Override
    public void connect() throws IOException {
        // Do nothing
    }
}.setDefaultUseCaches(false);

但是,选项 1 不是我想要的,因为它需要修改“generator.jar”,我现在可以这样做,但将来可能不会。 因此,唯一剩下的选项是在任务中使用分叉的 JVM,但是当我在 build.sbt 中设置时:

fork in Compile := true

获得的 runner 仍然使用与 sbt 本身相同的 JVM。

有人知道如何强制运行器在单独的 JVM 中启动吗?

附:我只认为分叉将有助于基于http://www.scala-sbt.org/0.13/docs/Running-Project-Code.html,因为当我第一次运行我的任务时,我看到:

异常:线程“run-main-0”中的 UncaughtExceptionHandler 抛出 sbt.TrapExitSecurityException

这是因为 AllMightyCompiler 当前以以下行结尾:

public static void main(String... args) {
     … lot of code ...              
     System.exit(exit);
}

【问题讨论】:

    标签: scala sbt


    【解决方案1】:

    在对 sbt/sbt gitter 频道进行简短讨论后,我被告知要使用:

    fork in (Compile, run) := true
    

    但同时获得跑步者为:

    val r = (runner in (Compile, run)).value 
    

    成功了:)

    【讨论】:

      猜你喜欢
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-28
      相关资源
      最近更新 更多