【问题标题】:sbt issues with my ClassBuilder implementation (Scala)我的 ClassBuilder 实现(Scala)存在 sbt 问题
【发布时间】:2018-11-14 14:47:02
【问题描述】:

Intellij 为我做了什么而 sbt 不是?

我正在开发一个 Scala 项目,我希望为其支持用户定义的插件类。我已经实现了 ClassLoader 的子类:

class PluginLoader(directory: String) extends ClassLoader {

  override def findClass(className: String): Class[_] = {
    val bytes = loadClassData(className)
    defineClass(className,bytes,0,bytes.length)
  }

  def loadClassData(className: String): Array[Byte] = {
    val fileName = className.replace('.',File.separatorChar) + ".class"
    val file = new File(directory,fileName)
    val bytes = new Array[Byte](file.length.toInt)
    val inputStream = new DataInputStream(new FileInputStream(file))
    inputStream.readFully(bytes)
    inputStream.close()
    bytes
  }
}

我用用户定义的目录和预编译的 scala 类的名称来调用它:

new PluginLoader(directory).loadClass(className).newInstance()

findClass 似乎成功地找到了用户提供的课程。但是,它会被再次调用以寻找scala.runtime.java8.JFunction2$mcIII$sp.class。它在用户提供的目录中查找,因此找不到加载的类。

这是我得到的错误:(run-main-0) java.io.FileNotFoundException: ./scala/runtime/java8/JFunction2$mcIII$sp.class (No such file or directory)

我已经在 Intellij 中成功运行了这个应用程序,这让我觉得我在 sbt 中缺少一些配置,而 Intellij 正在为我发现我的错误。

我需要做额外的配置吗?我应该加载整个 jar 文件而不是只传递一个类文件吗?

【问题讨论】:

    标签: java scala intellij-idea sbt runtime


    【解决方案1】:

    当你编译一个类时——不仅是 Scala 类,Java 类也是如此——那么这并不一定意味着你会得到一个 .class 文件。

    内部类、lambdas/闭包等会产生额外的字节码,这是运行所必需的,并且与“原始”类不在同一个文件中。

    据我所知,Java 创建了一些类,因为它是某个 lambda 的主体,而您没有加载它。

    底线是:您最好加载所有内容。 IntelliJ 可能只是将整个类路径传递给 JVM,因此您的类加载器甚至可能没有使用您的扩展(尽管您必须附加调试器才能确定)。

    【讨论】:

    • 谢谢。我已经继续加载了一个用 sbt-assembly 组装的 jar 文件。我现在遇到了一个不同的问题:java.lang.ClassCastException <myClass>$$Lambda$4456/762142833 cannot be cast to scala.Function2
    猜你喜欢
    • 2020-12-17
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 2019-06-28
    • 1970-01-01
    • 2015-12-05
    • 2016-07-28
    • 1970-01-01
    相关资源
    最近更新 更多