1

我正在使用xsbt-proguard-plugin,这是一个用于与 Proguard 一起工作的 SBT 插件。

我正在尝试为我编写的Hive Deserializer提供 Proguard 配置,它具有以下依赖项:

// project/Dependencies.scala
val hadoop      = "org.apache.hadoop"          %  "hadoop-core"          % V.hadoop
val hive        = "org.apache.hive"            %  "hive-common"          % V.hive
val serde       = "org.apache.hive"            %  "hive-serde"           % V.hive
val httpClient  = "org.apache.httpcomponents"  %  "httpclient"           % V.http 
val logging     = "commons-logging"            %  "commons-logging"      % V.logging
val specs2      = "org.specs2"                 %% "specs2"               % V.specs2      % "test"

加上一个非托管依赖:

// lib/UserAgentUtils-1.6.jar

因为其中大多数要么用于本地单元测试,要么在 Hadoop/Hive 环境中可用,我希望我的缩小 jarfile 只包括:

  • Java 类 SnowPlowEventDeserializer.class 和 SnowPlowEventStruct.class
  • org.apache.httpcomponents.httpclient
  • commons-logging
  • lib/UserAgentUtils-1.6.jar

但我真的很难让语法正确。我应该从我想要保留的类的白名单开始,还是明确过滤掉 Hadoop/Hive/Serde/Specs2 库?我知道这个 SO question,但它似乎不适用于这里。

如果我最初尝试白名单方法:

// Should be equivalent to sbt> package
import ProguardPlugin._
lazy val proguard = proguardSettings ++ Seq(
  proguardLibraryJars := Nil,
  proguardOptions := Seq(
    "-keepattributes *Annotation*,EnclosingMethod",
    "-dontskipnonpubliclibraryclassmembers",
    "-dontoptimize",
    "-dontshrink",
    "-keep class com.snowplowanalytics.snowplow.hadoop.hive.SnowPlowEventDeserializer",
    "-keep class com.snowplowanalytics.snowplow.hadoop.hive.SnowPlowEventStruct"
  )
)

然后我得到一个 Hadoop 处理错误,很明显 Proguard 仍在尝试捆绑 Hadoop:

proguard: java.lang.IllegalArgumentException: Can't find common super class of [[Lorg/apache/hadoop/fs/FileStatus;] and [[Lorg/apache/hadoop/fs/s3/Block;]

同时,如果我尝试使用 Proguard 的过滤语法来建立我不想包含的库的黑名单:

import ProguardPlugin._
lazy val proguard = proguardSettings ++ Seq(
  proguardLibraryJars := Nil,
  proguardOptions := Seq(
    "-keepattributes *Annotation*,EnclosingMethod",
    "-dontskipnonpubliclibraryclassmembers",
    "-dontoptimize",
    "-dontshrink",
    "-injars  !*hadoop*.jar"
  )
)

然后这似乎也不起作用:

proguard: java.io.IOException: Can't read [/home/dev/snowplow-log-deserializers/!*hadoop*.jar] (No such file or directory)

非常感谢任何帮助!

4

2 回答 2

1

白名单是正确的方法:ProGuard 应该得到一个完整的上下文,这样它就可以正确地剔除不需要的类、字段和方法。

错误“找不到公共超类”表明输入中仍然缺少某些库。ProGuard 可能警告过它,但配置似乎包含选项 -ignorewarnings 或 -dontwarn (应该避免)。您应该使用 -injars 或 -libraryjars 添加库。

如果 ProGuard 然后在输出中包含一些您不期望的类,您可以使用“-whyareyoukeeping class somepackage.SomeUnexpectedClass”获得解释。

从工作配置开始,您仍然可以尝试从输入中过滤掉类或整个 jar。过滤器被添加到类路径中的项目中,而不是单独添加,例如“-injars some.jar(!somepackage/**.class)”——cfr。手册。如果输入包含拖入其他不需要的类的测试类,这将很有用。

于 2012-05-29T17:11:40.973 回答
0

最后,我无法使用 Proguard 解决重复的类错误,更不用说如何弄清楚如何过滤掉相关的 jar,所以最终切换到了一种更简洁的 sbt-assembly方法:

-1。根据README将 sbt-assembly 插件添加到我的项目中

-2。使用标志更新了适当的项目依赖项,"provided"以阻止它们被添加到我的胖 jar 中:

val hadoop      = "org.apache.hadoop"          %  "hadoop-core"          % V.hadoop      % "provided"
val hive        = "org.apache.hive"            %  "hive-common"          % V.hive        % "provided"
val serde       = "org.apache.hive"            %  "hive-serde"           % V.hive        % "provided"
val httpClient  = "org.apache.httpcomponents"  %  "httpclient"           % V.http
val httpCore    = "org.apache.httpcomponents"  %  "httpcore"             % V.http  
val logging     = "commons-logging"            %  "commons-logging"      % V.logging     % "provided"
val specs2      = "org.specs2"                 %% "specs2"               % V.specs2      % "test"

-3。添加了一个 sbt-assembly 配置,如下所示:

import sbtassembly.Plugin._
import AssemblyKeys._
lazy val sbtAssemblySettings = assemblySettings ++ Seq(
  assembleArtifact in packageScala := false,
  jarName in assembly <<= (name, version) { (name, version) => name + "-" + version + ".jar" },
  mergeStrategy in assembly <<= (mergeStrategy in assembly) {
    (old) => {
      case "META-INF/NOTICE.txt" => MergeStrategy.discard
      case "META-INF/LICENSE.txt" => MergeStrategy.discard
      case x => old(x)
    }
  }
)

然后键入assembly生成了一个“胖 jar”,其中仅包含我需要的包,包括非托管依赖项,不包括 Hadoop/Hive 等。

于 2012-05-31T09:41:20.473 回答