问题 使用ProGuard混淆clojure uberjars


我想知道是否有人有任何混淆他们的leiningen编译的uberjars与proguard的经验。我已尽力在Google上寻找解决方案,但无法真正找到答案。我想知道这是否可能。

我一直试图模糊默认的lein项目。这是core.clj文件:

(ns proguard.core
(:gen-class))

(defn -main
  "I don't do a whole lot."
  [& args]
  (println "Hello, World!"))

项目文件:

(defproject proguard "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]]
  :aot :all
  :main proguard.core)

和我的proguard配置文件:

-injars clojure/proguard/target/proguard-0.1.0-SNAPSHOT-standalone.jar
-outjars clojure/test-project

-libraryjars /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/rt.jar

-dontshrink
-dontoptimize
-dontusemixedcaseclassnames
-dontpreverify
-dontnote
-printseeds

-keepclasseswithmembers public class * {
    public static void main(java.lang.String[]);
}

-keep class clojure.core__init { public static void load(); }
-keep class clojure.core_proxy__init { public static void load(); }
-keep class clojure.core_print__init { public static void load(); }
-keep class clojure.genclass__init { public static void load(); }
-keep class clojure.core_deftype__init { public static void load(); }
-keep class clojure.core.protocols__init { public static void load(); }
-keep class clojure.gvec__init { public static void load(); }
-keep class clojure.java.io__init { public static void load(); }
-keep class clojure.lang__init { public static void load(); }

-keep class proguard.core__init {
    public static void load();
}
-keep class proguard.core {
    public *** super*(...);
}

每当我尝试运行混淆的jar时,我都会遇到以下错误:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at clojure.lang.ve.<init>(Unknown Source)
    at clojure.lang.ve.c(Unknown Source)
    at clojure.lang.yf.a(Unknown Source)
    at proguard.core.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: clojure.lang.PersistentList, compiling:(clojure/core.clj:20)
    at clojure.lang.at.a(Unknown Source)
    at clojure.lang.at.b(Unknown Source)
    at clojure.lang.at.a(Unknown Source)
    at clojure.lang.bj.a(Unknown Source)
    at clojure.lang.at.a(Unknown Source)
    at clojure.lang.at.b(Unknown Source)
    at clojure.lang.at.a(Unknown Source)
    at clojure.lang.at.a(Unknown Source)
    at clojure.lang.at.a(Unknown Source)
    at clojure.lang.xh.a(Unknown Source)
    at clojure.lang.xh.a(Unknown Source)
    at clojure.lang.xh.b(Unknown Source)
    at clojure.lang.xh.d(Unknown Source)
    at clojure.lang.xh.c(Unknown Source)
    at clojure.lang.xh.<clinit>(Unknown Source)
    ... 4 more
Caused by: java.lang.ClassNotFoundException: clojure.lang.PersistentList
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at clojure.lang.ec.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at clojure.lang.xh.h(Unknown Source)
    at clojure.lang.bp.b(Unknown Source)
    at clojure.lang.bp.a(Unknown Source)
    at clojure.lang.bq.a(Unknown Source)
    ... 19 more

我不确定我在这里做错了什么......我试图遵循一个针对性的proguard教程 与proguard混淆,但它是android和ant特定的,所以我想知道使用lein的桌面应用程序的过程是否完全不同。

提前致谢。


8988
2017-09-05 12:24


起源

我没有使用proguard的经验,但是从堆栈跟踪看起来这个混淆器已经从uberjar中排除了clojure运行时。你必须保持 所有 clojure.jar中的类可以让你的程序工作,而不仅仅是几个 __init 从你的配置看起来像。我猜测并说你必须将clojure.jar添加到列表中 -libraryjars。 - Vladimir Matveev
嘿,谢谢你指点我正确的方向!整个clojure.jar确实需要留下来。我很快就会回答我自己的问题。 [编辑:嗯,我想我做不到,因为这个问题还太年轻......] - deadringer
现在你已经足够老了,你应该正确回答你自己的问题。就目前而言,问题面前的答案是令人困惑的。 - Tom
我现在已经这样做了。见下面的答案。 - deadringer


答案:


从上面复制:

混淆uberjars

1.准备project.clj文件

这是我的副本(简单,默认lein项目,带注释):

(defproject proguard "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]]
  :main proguard.core
  ;;; Make sure everything is aot compiled
  :aot :all
  ;;; Remove source .clj files from the resulting jar
  :omit-source true
  )

这里没有更多......还要确保(:gen-class) 包含在您的命名空间声明中。

建立uberjar lein uberjar 我们下一步了。

2.准备ProGuard配置文件

我的文件的副本再次带有注释

# Our uberjar
-injars clojure/proguard/target/proguard-0.1.0-SNAPSHOT-standalone.jar
# Our output direcotry
-outjars clojure/obfuscated

# Link to rt.jar. I'm on a Mac so your path may differ
-libraryjars /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/rt.jar

# ProGuard options. Detailed explanation here http://proguard.sourceforge.net/index.html#manual/usage.html
-dontskipnonpubliclibraryclassmembers
-dontnote
-printseeds

# What we will be doing is obfuscating, shrinking and optimizing the jar. 
# If you experience any problems start out with obfuscation and add the 
# -dontoptimize  and the -dontshrink flags and see if it works.

# Tell proguard to leave the clojure runtime alone
# You would need to add any other classes that you wish to preserve here.
-keep class clojure.** { *; }

# Keep our core__init class
-keep class proguard.core__init {
    public static void load();
}

# Keep classes that contain a main method (otherwise we won't be able to run the jar)
-keepclasseswithmembers public class * {
    public static void main(java.lang.String[]);
}

而已。现在使用新配置文件运行proguard java -jar proguard.jar @myconfig.pro。你应该看到一堆输出 -printseeds flag(如果你不想看看proguard会保留哪些类,你当然可以删除它)。


13
2017-11-15 12:42