运行使用 SBT 和 ProGuard 构建的独立 jar 时出现 AbstractMethodError

Posted

技术标签:

【中文标题】运行使用 SBT 和 ProGuard 构建的独立 jar 时出现 AbstractMethodError【英文标题】:AbstractMethodError when running standalone jar built with SBT and ProGuard 【发布时间】:2011-05-28 14:00:59 【问题描述】:

我编写了一个简单的 Scala 应用程序,我想以独立的可执行 jar 的形式分发到没有 Scala 运行时的服务器。通过SBT run 调用时一切正常,但不是java -jar

当我通过 java 运行 jar 时,我得到以下未处理的异常:

Exception in thread "main" java.lang.AbstractMethodError: java.util.logging.Handler.publish(Ljava/util/logging/LogRecord;)V
    at java.util.logging.Logger.log(Logger.java:458)
    at net.lag.logging.Logger.log(Logger.scala:108)
    at net.lag.logging.Logger.log(Logger.scala:91)
    at net.lag.logging.Logger.info(Logger.scala:121)
    at com.rentawebgeek.sitewiki.SiteWiki$.main(SiteWiki.scala:29)
    at com.rentawebgeek.sitewiki.SiteWiki.main(SiteWiki.scala)
Exception in thread "Thread-0" java.lang.AbstractMethodError: java.util.logging.Handler.close()V
    at java.util.logging.LogManager.resetLogger(LogManager.java:682)
    at java.util.logging.LogManager.reset(LogManager.java:665)
    at java.util.logging.LogManager$Cleaner.run(LogManager.java:223)

我正在使用 Configgy,它是 Logger,并且根据 AbstractMethodError 的 javadocs,我认为它可能与 Scala/SBT 相关,使用的 Java 版本与我从 shell 中调用的 Java 版本不同。但是,java -version$JAVA_HOME/bin/java -version/usr/local/bin/scala 使用的)都匹配为 1.6.0_22。

我的 ProGuard 选项是:

//program entry point
override def mainClass: Option[String] = Some("com.rentawebgeek.sitewiki.SiteWiki")

//proguard
override def proguardOptions = List(
    "-keepclasseswithmembers public class *  public static void main(java.lang.String[]); ",
    "-dontoptimize",
    "-dontobfuscate",
    "-keep class *",
    proguardKeepLimitedSerializability,
    proguardKeepAllScala,
    "-keep interface scala.ScalaObject"
)

override def proguardInJars = Path.fromFile(scalaLibraryJar) +++ super.proguardInJars

如何解决此错误?或者找到另一种方法从 SBT 项目构建可执行 jar 以进行无 Scala 部署?

【问题讨论】:

【参考方案1】:

在 SiteWiki.scala 中的第 29 行查看您正在进行的调用;那是有问题的电话。您可能在那里使用抽象方法调用特征/类。很可能应该实现抽象方法的方法被 proguard 撕掉了(或者 Scala 覆盖不匹配(我已经看到这种情况发生))。

如果线路很长,无法找到有问题的电话;尝试分解多行。

【讨论】:

你是对的:ProGuard 正在删除一些重要的东西。目前,我可以通过删除我的-keep 选项并使用-dontshrink 来解决它。我现在不在乎罐子的大小。谢谢!【参考方案2】:

最新的 ProGuard 版本包含用于处理 Scala 应用程序和 Scala 运行时的示例配置:

http://proguard.sourceforge.net/manual/examples.html#scala

如果这不起作用,-printconfiguration 的输出和控制台输出可能有助于找到根本原因。

【讨论】:

以上是关于运行使用 SBT 和 ProGuard 构建的独立 jar 时出现 AbstractMethodError的主要内容,如果未能解决你的问题,请参考以下文章

如何签署我的 ProGuard 的 Scala 独立 JAR?

如何告诉 sbt-proguard 包含 java *.jars?

ProGuard 使用 sbt-proguard 说 Unsupported class version number [52.0] (maximum 51.0, Java 1.7)

使用 scala sbt 构建一个独立的 jar 以合并到一个 android 项目中

SBT ProGuard 插件:OutOfMemoryError,如何增加堆空间?

如何更新 sbt android-plugin 的 ProGuard 版本?