1

私はxsbt-proguard-pluginを使用しています。これは、Proguardを操作するためのSBTプラグインです。

私が書いたHiveDeserializerの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環境内で利用できるため、縮小したjarファイルには次のものだけを含める必要があります。

  • JavaクラスSnowPlowEventDeserializer.classおよびSnowPlowEventStruct.class
  • org.apache.httpcomponents.httpclient
  • commons-logging
  • lib/UserAgentUtils-1.6.jar

しかし、私は構文を正しくするのに本当に苦労しています。保持したいクラスのホワイトリストから開始する必要がありますか、それともHadoop / Hive / Serde / Specs2ライブラリを明示的に除外する必要がありますか?私はこのSOの質問を知っていますが、ここでは当てはまらないようです。

最初にホワイトリストアプローチを試した場合:

// 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

0

結局、関連する jar を除外する方法を理解する方法は言うまでもなく、Proguard を使用してクラスの重複エラーを回避できなかったため、最終的にはよりクリーンなsbt アセンブリアプローチに切り替えました。

-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と、管理されていない依存関係を含め、Hadoop/Hive などを除いて、必要なパッケージだけを含む「ファット jar」が生成されました。

于 2012-05-31T09:41:20.473 に答える