【问题标题】:scala runtime reflect sometimes throws exceptionscala运行时反映有时会抛出异常
【发布时间】:2013-12-05 22:20:33
【问题描述】:
object Reflects {

  def mirror() = universe.runtimeMirror(getClass.getClassLoader)

  def caseFields(x: AnyRef) = {
    val instanceMirror = mirror().reflect(x)
    instanceMirror.symbol.typeSignature.members.collect {
      case m: MethodSymbol if (m.isCaseAccessor) => m.name.toString -> instanceMirror.reflectMethod(m).apply()
    }
  }

}

当我在其他类中调用caseFields 方法时,我定义了一个对象Reflects

有时此方法会引发以下异常

java.lang.UnsupportedOperationException: tail of empty list
at scala.collection.immutable.Nil$.tail(List.scala:339) ~[scala-library.jar:na]
at scala.collection.immutable.Nil$.tail(List.scala:334) ~[scala-library.jar:na]
at scala.reflect.internal.SymbolTable.popPhase(SymbolTable.scala:172) ~[scala-reflect.jar:na]

还有其他奇怪的例外。

这个方法有什么问题

【问题讨论】:

  • 您的堆栈跟踪没有显示在您的代码中引发异常的位置。我推测您没有检查members 大小。
  • @pedrofurla 即使成员大小为零。此方法应返回空地图。我认为这与 scala-reflect 相关
  • 你能发布完整的堆栈跟踪吗?另外,您是否在多个线程中运行此方法?
  • @jilen 非常真实,我很傻。
  • @EugeneBurmako 我在一个或多个 akka actor 中调用该方法。

标签: scala scala-compiler


【解决方案1】:

在 2.10.3 中(可能在 2.10.4 中,因为看起来我们没有时间从 2.11.0-M7 向后移植修复程序),运行时反射不是线程安全的: http://docs.scala-lang.org/overviews/reflection/thread-safety.html。您的堆栈跟踪是问题的众多可能表现之一。

坏消息是,在 2.10.x 中,除了将所有反射操作放在同步块中之外,没有解决线程不安全问题的解决方法。好消息是在 2.11.0 中这个问题应该已经消失了。

【讨论】:

  • 那么,如果我把同步到方法,这个问题应该是固定的?
  • 只要你不在程序的其他任何地方做运行时反射。
  • 但是第三方库很多,不知道会不会用到运行时反射,倒霉……
  • 我将尝试在 2.10.4 或 2.10.5 中进行反向移植
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 2015-06-03
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 2016-06-15
相关资源
最近更新 更多