Mec*_*ail 7 java reflection jvm scala runtime
我有一个简单的应用程序:
object Test extends App {
implicit def t2mapper[X, X0 <: X, X1 <: X](t: (X0, X1)) = new {
def map[R](f: X => R) = (f(t._1), f(t._2))
}
println("Hello!")
val (foo, bar) = (1, 2) map (_ * 2)
println((foo, bar))
}
Run Code Online (Sandbox Code Playgroud)
(这t2mapper是答案.)
代码编译正常:
$ scalac -version
Scala compiler version 2.9.1 -- Copyright 2002-2011, LAMP/EPFL
$ scalac -unchecked Test.scala
$
Run Code Online (Sandbox Code Playgroud)
但是当它运行时,它会抛出一个IllegalAccessError(在 Hello!打印之前):
$ java -version
java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.1) (6b24-1.11.1-4ubuntu3)
OpenJDK Server VM (build 20.0-b12, mixed mode)
$ scala Test
java.lang.IllegalAccessError: tried to access field Test$.reflParams$Cache1 from class Test$delayedInit$body
at Test$delayedInit$body.(Test.scala:6)
at Test$.(Test.scala:1)
at Test$.(Test.scala)
at Test.main(Test.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:78)
at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88)
at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78)
at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
请注意,最后两行替换为
println((1, 2) map (_ * 2))
Run Code Online (Sandbox Code Playgroud)
要么
val (foo, bar) = (2, 4)
println((foo, bar))
Run Code Online (Sandbox Code Playgroud)
要么
val intermediate = (1, 2) map (_ * 2)
val (foo, bar) = intermediate
println((foo, bar))
Run Code Online (Sandbox Code Playgroud)
它(2,4)按预期打印.但当包裹在一个街区
{
val intermediate = (1, 2) map (_ * 2)
val (foo, bar) = intermediate
println((foo, bar))
}
Run Code Online (Sandbox Code Playgroud)
要么
private val blah = {
val intermediate = (1, 2) map (_ * 2)
val (foo, bar) = intermediate
println((foo, bar))
}
Run Code Online (Sandbox Code Playgroud)
它引发了异常.
为什么第一种和最后一种方式会导致JVM在运行时抛出错误?
看起来有一些相关的开放漏洞.例如,这个可能是相关的:
请注意,您也可以创建一个main方法而不是扩展App,它将起作用.
编辑:
当你使用这一行时(我扩展了隐含的):
val (foo, bar) = t2mapper((1, 2)) map (_ * 2)
Run Code Online (Sandbox Code Playgroud)
然后鼠标悬停foo或bar在Eclipse中显示private[this] val foo.
因此,它似乎与SI-5251非常相似.