【问题标题】:Unexpected behavior with scala and URLClassLoaderscala 和 URLClassLoader 的意外行为
【发布时间】:2019-10-02 00:24:56
【问题描述】:

我在尝试使用 URLClassLoader 加载类时发现了一种有线行为。

一点上下文:我在 jar1 有一个特征,如下所示:

trait ATrait { def act(context: Context): Unit }

jar2 中的类看起来像这样(jar2 在 IDE 的类路径中获得了 jar1):

class EntryPoint extends ATrait {
  override def act(context: Context): Unit = {
    println(s"Hello World! context is = $context")
  }
}

回到 jar1,我有一个程序入口点,如下所示:

  private val classloader = new URLClassLoader(Array(jar2.toURI.toURL))
  private val myClass = classloader.loadClass(jar2ClassName)
  private val instance = myClass.newInstance().asInstanceOf[ATrait]

  instance.act(null)

然后,我尝试从我的 IDE(IntelliJ + sbt) 运行程序,它按预期运行。

后来我使用 scala 命令从我的 cli 运行 jar1,我得到了这个错误:java.lang.ClassNotFoundException: core.ATrait,女巫很奇怪,因为 jar1 包含 core.ATrait。

经过大量修改后,我从 jar1 中创建了一个胖 jar(带有 sbt 程序集)并使用 java 命令运行它,它按预期工作。

所以在这个长篇故事之后,我的问题是:

  1. 为什么 scala 命令不像 java 那样工作?
  2. java 和 scala 有不同的类加载器吗?
  3. 是否有一种解决方法可以让我使用 scala 运行 jar1?

注意:我使用的是 scala 2.13

编辑:

scala 命令是“scala -classpath .\jar1.jar core.EntryPoint .\jar2.jar”

java 命令是“java -classpath .\fatjar1.jar core.EntryPoint .\jar2.jar” (我在 args 中传递 jar2 位置)

【问题讨论】:

  • 您能否发布您用于从类似界面的命令中运行 jar1 的确切命令?
  • @Виталий Олегович 我将其添加到问题中

标签: scala


【解决方案1】:

正确的命令是作为最后一个参数运行的类:

scala -classpath .\jar1.jar .\jar2.jar core.EntryPoint

【讨论】:

    【解决方案2】:

    经过一番环顾后,似乎 scala 脚本使用了一个名为 MainGenericRunner 的对象来运行代码,而该对象使用了一个 URLClassLoader 它的自身,所以在 java 之间有一个不同的类加载器。 exe 和 scala 脚本。

    解决方法是在类路径中提供给 java scala-library.jar,它就像魅力一样工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-23
      • 2013-01-31
      • 2018-06-17
      • 1970-01-01
      • 2017-03-27
      • 2011-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多