【问题标题】:scala.tools.reflect.ToolBoxError: reflective compilation has failed: cannot initialize the compiler due to java.lang.VerifyErrorscala.tools.reflect.ToolBoxError:反射编译失败:由于 java.lang.VerifyError 无法初始化编译器
【发布时间】:2021-07-21 03:19:18
【问题描述】:

我想传递一个包含案例类的 scala 文件,以便我的应用程序在运行时编译此案例类并开始使用它。

我这样做的主要原因是因为我想避免每次案例类更改时都重新构建我的代码。所以最好将它作为参数传递(如果您想知道,这个案例类的操作是通用的,因此不需要在转换中进行任何返工)

我使用这些post1post2post3 作为参考。到目前为止,我的应用程序如下所示:

import scala.io.Source
import scala.reflect.runtime.universe
import scala.tools.reflect._

object TestCompile {
  def main(args: Array[String]): Unit = {

    val path = "C:\\myWorkspace\\entity\\TestClass.scala"
    val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
    val src = Source.fromFile(path).mkString.stripMargin
    val clazz = tb.compile(tb.parse(src))().asInstanceOf[Class[_]]

  }
}

TestClass.scala文件是这样的:

case class TestClass(
         val value : String,
         val timeStamp : Long,
         val rowKey : String,
         val columnFamily : String
)

但是我遇到了一个例外

val clazz = tb.compile(tb.parse(src))().asInstanceOf[Class[_]]

例外:

线程“主”scala.tools.reflect.ToolBoxError 中的异常: 反射编译失败:由于无法初始化编译器 到 java.lang.VerifyError: scala/工具/反射/ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$api$.liftedTree1$1(ToolBoxFactory.scala:344) 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$api$.compiler$lzycompute(ToolBoxFactory.scala:330) 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$api$.compiler(ToolBoxFactory.scala:329) 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.liftedTree2$1(ToolBoxFactory.scala:356) 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.apply(ToolBoxFactory.scala:354) 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.parse(ToolBoxFactory.scala:413) 在 TestCompile$.main(App.scala:17) 在 TestCompile.main(App.scala) 引起:java.lang.VerifyError: scala/工具/反射/ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$api$.liftedTree1$1(ToolBoxFactory.scala:334)

以下是我正在使用的依赖项,但是我尝试使用其他版本时总是遇到相同的错误:

<dependency>
  <groupId>org.scala-lang</groupId>
  <artifactId>scala-reflect</artifactId>
  <version>2.11.6</version>
</dependency>

我做错了什么?

【问题讨论】:

    标签: scala reflection scala-reflect


    【解决方案1】:

    我无法复制VerifyError

    我有

    java.lang.ClassCastException: scala.runtime.BoxedUnit cannot be cast to java.lang.Class
    

    val clazz = tb.compile(tb.parse(src))().asInstanceOf[Class[_]] 行中。

    tb.compile(tb.parse(src)) 的类型为 () =&gt; Any,因此 tb.compile(tb.parse(src))() 的类型为 Any

    https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/reflect/ToolBox.scala#L129

    删除.asInstanceOf[Class[_]]

    另见Causes of getting a java.lang.VerifyError

    【讨论】:

      【解决方案2】:

      我今天有时间测试一下。我认为的主要问题是 TestClass.scala 中缺少最后一行 scala.reflect.classTag[TestClass].runtimeClass

      要记住的另一件重要事情是scala-compiler.jar 也应该在您的类路径中。

      一旦我解决了这个问题,我又遇到了 Java/Scala 对象转换的另一个问题。您有两个选择,将timeStamp 字段设为StringJava.lang.Long。由于字符串转换很简单,我在下面给出了Java.lang.Long 的示例。

      通过上述更改,我的 TestClass.scala 如下所示:

      case class TestClass(
                            value : String,
                            timeStamp : java.lang.Long,
                            rowKey : String,
                            columnFamily : String
                          ) {}
      
      scala.reflect.classTag[TestClass].runtimeClass
      

      我把它复制到/tmp/目录进行测试。

      测试

      我的 TestCompile.scala 如下所示:

      import scala.io.Source
      import scala.reflect.runtime.universe
      import scala.tools.reflect._
      
      object TestCompile {
        def main(args: Array[String]): Unit = {
      
          val path = "/tmp/TestClass.scala"
          val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
          val src = Source.fromFile(path).mkString.stripMargin
          println(src)
          val clazz = tb.compile(tb.parse(src))().asInstanceOf[Class[_]]
      
          val ctor = clazz.getDeclaredConstructors()(0)
          val instance = ctor.newInstance("My value", new java.lang.Long(1234567890L), "Row1", "Column1")
          println(instance.toString)
      
        }
      }
      

      输出

      TestClass(My value,1234567890,Row1,Column1)
      

      【讨论】:

        【解决方案3】:

        因为你失去了依赖将这些依赖添加到你的 pom.xml

        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.11.8</version>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-reflect</artifactId>
            <version>2.11.8</version>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-compiler</artifactId>
            <version>2.11.8</version>
        </dependency>
        

        【讨论】:

          猜你喜欢
          • 2010-10-29
          • 2021-09-08
          • 1970-01-01
          • 2016-03-27
          • 2023-03-29
          • 2016-11-30
          • 2015-06-14
          相关资源
          最近更新 更多