目录[-]
两个工程 Project1,Project2(将被混淆的工程)。Project1 将通过 Maven 依赖配置的方式引用混淆后的 Project2。后面我会详细介绍 pom.xml 的配置。
该 pom.xml 比较简单主要通过 classifier 来判断是否使用混淆的 Jar(Project2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
project
xmlns
=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<
modelVersion
>4.0.0
modelVersion
>
<
groupId
>org.noahx.proguard.example
groupId
>
<
artifactId
>project1
artifactId
>
<
version
>1.0-SNAPSHOT
version
>
<
dependencies
>
<
dependency
>
<
groupId
>org.noahx.proguard.example
groupId
>
<
artifactId
>project2
artifactId
>
<
classifier
>pg
classifier
>
<
version
>1.0-SNAPSHOT
version
>
dependency
>
dependencies
>
project
>
|
pom.xml 中配置的 proguard-maven-plugin 来做混淆,详细说明见注释。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
project
xmlns
=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<
modelVersion
>4.0.0
modelVersion
>
<
groupId
>org.noahx.proguard.example
groupId
>
<
artifactId
>project2
artifactId
>
<
version
>1.0-SNAPSHOT
version
>
<
build
>
<
plugins
>
<
plugin
>
<
groupId
>com.github.wvengen
groupId
>
<
artifactId
>proguard-maven-plugin
artifactId
>
<
version
>2.0.7
version
>
<
executions
>
<
execution
>
<
phase
>package
phase
>
<
goals
>
<
goal
>proguard
goal
>
goals
>
execution
>
executions
>
<
configuration
>
<
attach
>true
attach
>
<
attachArtifactClassifier
>pg
attachArtifactClassifier
>
<
options
>
<
option
>-ignorewarnings
option
>
<
option
>-dontshrink
option
>
<
option
>-dontoptimize
option
>
<
option
>-dontskipnonpubliclibraryclasses
option
>
<
option
>-dontskipnonpubliclibraryclassmembers
option
>
<
option
>-repackageclasses org.noahx.proguard.example.project2.pg
option
>
<
option
>-keep class **.package-info
option
>
<
option
>-keepattributes Signature
option
>
<
option
>-keepattributes SourceFile,LineNumberTable,*Annotation*
option
>
<
option
>-keepclassmembers enum org.noahx.proguard.example.project2.** { *;}
option
>
<
option
>-keep class org.noahx.proguard.example.project2.bean.** { *;}
option
>
<
option
>-keep class org.noahx.proguard.example.project2.Project2 { public void init(); public void
destroy(); }
option
>
options
>
<
outjar
>${project.build.finalName}-pg
outjar
>
<
libs
>
<
lib
>${java.home}/lib/rt.jar
lib
>
libs
>
configuration
>
plugin
>
plugins
>
build
>
project
>
|
这里只比较 Project2 类的不同。其它类的比较,请大家使用 jd-gui 等反编译工具进行比较。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package
org.noahx.proguard.example.project2;
import
org.noahx.proguard.example.project2.dao.TestDao;
import
org.noahx.proguard.example.project2.impl.User;
/**
* Created by noah on 8/20/14.
*/
public
class
Project2 {
public
void
init() {
test1();
test2();
}
private
void
test1() {
Status on = Status.valueOf(
"On"
);
switch
(on) {
case
On: {
}
break
;
case
Off: {
}
break
;
}
}
private
void
test2() {
TestDao testDao=
new
TestDao();
User user=
new
User();
user.setUserid(
"abc"
);
user.setPassword(
"pwd"
);
user.setDescription(
"des"
);
testDao.save(user);
}
private
void
test3() {
}
private
void
test4() {
}
private
void
throwException() {
throw
new
RuntimeException(
"hello"
);
}
public
void
destroy() {
test3();
test4();
throwException();
}
}
|
所有没有指定 keep 的内容都变为了 a,b,c...,增大了阅读难度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
package
org.noahx.proguard.example.project2;
import
org.noahx.proguard.example.project2.pg.a;
public
class
Project2
{
public
void
init()
{
b();
c();
}
private
void
b() {
b localb = b.valueOf(
"On"
);
switch
(a.a[localb.ordinal()])
{
case
1
:
break
;
case
2
:
}
}
private
void
c()
{
a locala =
new
a();
org.noahx.proguard.example.project2.pg.b localb =
new
org.noahx.proguard.example.project2.pg.b();
localb.a(
"abc"
);
localb.b(
"pwd"
);
localb.c(
"des"
);
locala.a(localb);
}
private
void
d()
{
}
private
void
e() {
}
public
void
a() {
throw
new
RuntimeException(
"hello"
);
}
public
void
destroy() {
d();
e();
a();
}
}
|
使用 ProGuard 产生的 Jar 包,会发生无法定位 Jar 中资源的问题。原因不详,我没有太深入研究。
使用 [类名].class.getResource(),Thread.currentThread().getContextClassLoader().getResource(),不论是否以“/”开头都返回 null。没有混淆的 Jar 是没有这个问题的。
我使用了一种直接读取 Jar 中内容的方式来解决。
1
2
3
4
5
6
7
8
9
10
11
12
|
final
File jarFile =
new
File([类名].
class
.getProtectionDomain().getCodeSource().getLocation().getPath());
//定位类所在的 Jar 文件
if
(jarFile.isFile()) {
final
JarFile jar =
new
JarFile(jarFile);
Enumeration
while
(entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if
(entry.getName().startsWith(
"org/noahx"
)) {
InputStream entryInputStream = jarFile.getInputStream(entry);
//遍历包中的内容来获得资源
}
}
jar.close();
}
|
使用 proguard-maven-plugin 插件,既保持了 Maven 的依赖模式,又满足了我的混淆需求。其它详细的参数配置,大家可以参考官方文档。
ProGuard 满足了我的需求。至于是好是坏,希望大家不要围绕这点做没有必要的争论,谢谢。
样例程序下载:http://pan.baidu.com/s/1dDGNoDr