我已经创建了一个简单的Scala控制台应用程序.我运行它sbt run并在退出时始终收到以下异常:
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 17 s, completed 30.01.2014 22:19:37
Run Code Online (Sandbox Code Playgroud)
之后我的所有控制台输出都变得不可见.我可以输入和运行应用程序,但我看不到我在键入的内容.
这个例外是什么意思?我究竟做错了什么?
cfe*_*uke 10
在SBT会话中运行控制台应用程序时,可以派生JVM.这样,当您的控制台应用程序退出时,它不会杀死托管的sbt JVM.我正在为main集成测试配置中的类做这个.
在build.sbt(或等效的sbt项目配置文件中):
fork in (IntegrationTest, run) := true
Run Code Online (Sandbox Code Playgroud)
(您可能只想fork in run := true覆盖控制台主机).然后在任何扩展的类App:
package com.example
object StuffMain extends App {
println("stuff")
sys.exit(0) // 0 is a successful Unix exit code
}
Run Code Online (Sandbox Code Playgroud)
(sys.exit如果您的应用程序没有使分叉的JVM保持活动状态,则可能根本不需要调用.)
在我的情况下,我可以StuffMain通过运行执行此集成测试:
sbt> it:runMain com.example.StuffMain
Run Code Online (Sandbox Code Playgroud)
目前尚不清楚您使用的是什么SBT版本,但使用SBT 0.13.2-M1时,可以通过以下类轻松复制:
Hello.scala
object ExitApp extends App {
exit(0)
}
Run Code Online (Sandbox Code Playgroud)
该类确切地显示何时sbt.TrapExitSecurityException抛出异常 - 每当调用方法java.lang.Runtime.exit(int)时.
$ sbt run
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Loading project definition from /Users/jacek/sandbox/so/TrapExitSecurityException/project
[info] Set current project to trapexitsecurityexception (in build file:/Users/jacek/sandbox/so/TrapExitSecurityException/)
[warn] there were 1 deprecation warning(s); re-run with -deprecation for details
[warn] one warning found
[info] Running ExitApp
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 6 s, completed Jan 30, 2014 9:05:24 PM
Run Code Online (Sandbox Code Playgroud)
从您的应用程序中删除该调用,该异常消失.根据sbt.TrapExitscaladoc:
只应通过分支新的JVM来调用此类代码.
你为什么一直使用它?
此异常不是错误。
SBT 只是警告您正在运行的应用程序调用了sys.exit(0). SBT 不会终止 JVM(并在同一场合终止 SBT),而是会拦截该调用并保持 JVM 运行,以便您可以继续与 SBT 交互。
我通过检查SBT的源代码找到了这个解释:
/** SecurityManager hook to trap calls to `System.exit` to avoid shutting down the whole JVM.*/
override def checkExit(status: Int): Unit = if (active) {
val t = currentThread
val stack = t.getStackTrace
if (stack == null || stack.exists(isRealExit)) {
exitApp(t, status)
throw new TrapExitSecurityException(status)
}
}
Run Code Online (Sandbox Code Playgroud)