scala .tools.reflect.ToolBoxError: не удалось отразить компиляцию: не удалось инициализировать компилятор из-за java .lang.VerifyError - PullRequest
0 голосов
/ 09 января 2020

Я хочу передать файл scala, содержащий класс дел, чтобы мое приложение компилировало этот класс дел во время выполнения и начал использовать его.

Основная причина, по которой я это делаю, заключается в том, что я хочу Старайтесь не перестраивать мой код каждый раз, когда меняется класс case. Поэтому было бы лучше передать его как параметр (в случае, если вам интересно, операции с этим классом дел являются обобщенными c, поэтому не требуется никаких переделок в преобразованиях)

Я использовал эти post1 , post2 и post3 в качестве ссылок. Пока мое приложение выглядит так:

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[_]]

Исключение:

Исключение в потоке "main" scala .tools.reflect.ToolBoxError: сбой компиляции с отражением: невозможно инициализировать компилятор из-за java Ошибка tools.reflect.ToolBoxFactory $ ToolBoxImpl $ withCompilerApi $ api $ .compiler $ lzycompute (ToolBoxFactory. scala: 330) в scala .tools.reflect.ToolBoxFactory $ ToolBoxImpl $ сCompilerApi $ api $ comp. : 329) в scala .tools.reflect.ToolBoxFactory $ ToolBoxImpl $ withCompilerApi $ .liftedTree2 $ 1 (ToolBoxFactory. scala: 356) в scala .tools.reflect.ToolBoxFactory $ ToolBoxImpl для $. scala: 354) на scala .tools.re flect.ToolBoxFactory $ ToolBoxImpl.parse (ToolBoxFactory. scala: 413) в TestCompile $ .main (Приложение. scala: 17) в TestCompile.main (Приложение. scala). Причина: java .lang. VerifyError: scala / tools / refle / 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>

Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 23 января 2020

У меня есть время проверить это сегодня. Основная проблема, я думаю, состоит в том, что последняя ожидаемая строка scala.reflect.classTag[TestClass].runtimeClass отсутствует в TestClass. scala.

Еще одна важная вещь, которую следует помнить, это то, что scala-compiler.jar также должно быть в ваш путь к классу.

Как только я решил это, я столкнулся с другой проблемой с преобразованием объектов Java / Scala. У вас есть два варианта, сделать поле timeStamp либо String, либо Java.lang.Long. Поскольку преобразование String тривиально, ниже приведен пример для 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)
1 голос
/ 10 января 2020

Я не могу воспроизвести 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)) имеет тип () => 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[_]].

Также см. Причины получение java .lang.VerifyError

...