proguard 可以忽略库中未使用的类吗?
我有一个使用 pdfbox 库的 java 应用程序,它有 10mb。我只使用这个库的几个类。
我认为 ProGuard 会为我的应用程序生成一个独立的 jar。但是ProGuard生成的jar仍然需要/lib文件夹中的pdfbox.jar才能运行。我做错了什么吗?我怎样才能实现我的目标? (省略了 99% 我不使用的库类)。
评论后备注: - 原始 jar 及其库是使用 Netbeans 生成的。我首先使用 ProGuard GUI,但根据我收到的关于这个问题的评论,我转而使用脚本。结果相同:仅当库位于 jar 旁边的 /lib 文件夹中时,应用程序才能工作。
混淆器脚本:
-injars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\ZoText.jar"
-outjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\ZoText_short.jar"
-libraryjars <java.home>/lib/rt.jar
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\Boilerpipe_short.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\commons-io-2.1.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\commons-lang3-3.0.1.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\guava-10.0.1.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\nekohtml.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\pdfbox-app-1.6.0.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\xercesImpl.jar"
-printmapping proguard.map
-keep public class proguard.ProGuard {
public static void main(java.lang.String[]);
}
-keepparameternames
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keep public class * {
public protected *;
}
-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String, boolean);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
I have a java application using the pdfbox library, which makes 10mb. I use just a few classes of this library.
I thought that ProGuard would generate a standalone jar for my application. But the jar generated by ProGuard still needs the pdfbox.jar in the /lib folder to run. Am I doing something wrong? How could I achieve my goal? (leaving out the 99% of the library classes I don't use).
Note after comments:
- the original jar and its libraries are generated with Netbeans. I first used ProGuard GUI but following the comments I received on this question, I switched to scripting. Same result: the app works only when the libraries are in a /lib folder next to the jar.
The Proguard script:
-injars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\ZoText.jar"
-outjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\ZoText_short.jar"
-libraryjars <java.home>/lib/rt.jar
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\Boilerpipe_short.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\commons-io-2.1.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\commons-lang3-3.0.1.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\guava-10.0.1.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\nekohtml.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\pdfbox-app-1.6.0.jar"
-libraryjars "C:\Users\C. Levallois\Documents\NetBeansProjects\ZoText\dist\lib\xercesImpl.jar"
-printmapping proguard.map
-keep public class proguard.ProGuard {
public static void main(java.lang.String[]);
}
-keepparameternames
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keep public class * {
public protected *;
}
-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String, boolean);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
-libraryjars
保存假定可在运行时供优化的应用程序使用的代码。也就是说,Proguard 不会将它们包含在其输出中;它只需要它们作为参考,因为它正在处理-injars
中的代码。暂时去掉 Proguard:如果没有这个库类,您原来的未优化的 JAR 也无法工作,对吧? Proguard 并没有改变这一点。
如果您希望将其打包在优化输出中,则它必须存在于输入中。您必须首先将这些额外的 jar 包含为
-injars
或 JARred 以及输入,以便它们出现在输出中。但是,是的:Proguard 可以删除未使用的类,包括您从其他库内置的类(如果您对其进行配置)。
The
-libraryjars
hold code that is assumed to be available to your optimized app at runtime. That is, Proguard does not include them in its output; it merely needs them for reference as it is processing the code in-injars
.Take away Proguard for a moment: your original unoptimized JAR doesn't work without this library class either, right? Proguard doesn't change that.
If you want it to be packaged up together in the optimized output it has to be present in the input. You would have to include these extra jars as
-injars
, or JARred up together with the input in the first place in order for them to appear in the output.But, yes: Proguard can strip out unused classes, including those that you built in from this other library, if you configure it to.
虽然对你来说已经太晚了,但这里的工具完全可以满足你的需求:
该工具 minimize-jar 删除未使用的类并根据
verbose:class
信息创建一个 uber jar。它只有 5KB 并且没有依赖性。Though it's too late for you, here is the tool doing exactly you wanted:
The tool minimize-jar removes unused classes and creates a uber jar based on
verbose:class
information. It's only 5KB and has no dependency.根据我对手册的阅读,ProGuard 确实为它处理的 JAR 文件遗漏了未使用的类。所以我怀疑您没有处理
pdfbox.jar
文件;即你只需将它放在类路径上即可。我建议您从脚本而不是 GUI 运行 Proguard。这将允许您将混淆步骤合并到您的主要构建脚本中,对脚本进行版本控制,并...向其他人展示脚本以获得他们的建议/帮助。
According to my reading of the manual, ProGuard does leave out unused classes for the JAR files that it process. So I suspect that you are not processing the
pdfbox.jar
file; i.e. you just have it on the classpath.I recommend that you run Proguard from a script rather than the GUI. This will allow you to incorporate the obfuscation step into your main build scripts, version control the scripts and ... show other people the script to get their advice / help.