maven混淆Java代码

Maven 环境下使用 proguard-maven-plugin 插件混淆你的源码

时间 2014-08-20 15:23:56 肖国颖的个人页面

原文  http://my.oschina.net/noahxiao/blog/304746

主题 Maven

一、场景介绍

两个工程 Project1,Project2(将被混淆的工程)。Project1 将通过 Maven 依赖配置的方式引用混淆后的 Project2。后面我会详细介绍 pom.xml 的配置。

二、Maven 配置

1、Project1 的 pom.xml

该 pom.xml 比较简单主要通过 classifier 来判断是否使用混淆的 Jar(Project2)

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

2、Project2 的 pom.xml

pom.xml 中配置的 proguard-maven-plugin 来做混淆,详细说明见注释。

<?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>
          <!-- attach 的作用是在 install 与 deploy 时将生成的 pg 文件也安装与部署 -->
          <options> <!-- 详细配置方式参考 ProGuard 官方文档 -->
            <!--<option>-dontobfuscate</option>-->
            <option>-ignorewarnings</option> <!--忽略所有告警-->
            <option>-dontshrink</option>   <!--不做 shrink -->
            <option>-dontoptimize</option> <!--不做 optimize -->
            <option>-dontskipnonpubliclibraryclasses</option>
            <option>-dontskipnonpubliclibraryclassmembers</option>

            <option>-repackageclasses org.noahx.proguard.example.project2.pg</option>
            <!--平行包结构(重构包层次),所有混淆的类放在 pg 包下-->

            <!-- 以下为 Keep,哪些内容保持不变,因为有一些内容混淆后(a,b,c)导致反射或按类名字符串相关的操作失效 -->

            <option>-keep class **.package-info</option>
            <!--保持包注解类-->

            <option>-keepattributes Signature</option>
            <!--JAXB NEED,具体原因不明,不加会导致 JAXB 出异常,如果不使用 JAXB 根据需要修改-->
            <!-- Jaxb requires generics to be available to perform xml parsing and without this option ProGuard was not retaining that information after obfuscation. That was causing the exception above. -->

            <option>-keepattributes SourceFile,LineNumberTable,*Annotation*</option>
            <!--保持源码名与行号(异常时有明确的栈信息),注解(默认会过滤掉所有注解,会影响框架的注解)-->

            <option>-keepclassmembers enum org.noahx.proguard.example.project2.** { *;}</option>
            <!--保持枚举中的名子,确保枚举 valueOf 可以使用-->

            <option>-keep class org.noahx.proguard.example.project2.bean.** { *;}</option>
            <!--保持 Bean 类,(由于很多框架会对 Bean 中的内容做反射处理,请根据自己的业务调整) -->

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

三、Java 混淆前后内容比较

这里只比较 Project2 类的不同。其它类的比较,请大家使用 jd-gui 等反编译工具进行比较。

1、混淆前的 Project2 类

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();
  }
}

2、混淆后的 Project2 类

所有没有指定 keep 的内容都变为了 a,b,c...,增大了阅读难度。

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 中内容的方式来解决。

final File jarFile = new File([类名].class.getProtectionDomain().getCodeSource().getLocation().getPath()); //定位类所在的 Jar 文件
      if(jarFile.isFile()) {
        final JarFile jar = new JarFile(jarFile);
        Enumeration<JarEntry> entries = jar.entries();
        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 满足了我的需求。至于是好是坏,希望大家不要围绕这点做没有必要的争论,谢谢。

时间: 2024-08-04 23:10:20

maven混淆Java代码的相关文章

Jocky混淆JAVA代码(保护你的JAVA项目)

1.1 什么是Jocky? 我们知道,Java是一种跨平台的编程语言,其源码(.java文件)被编译成与平台无关的字节码(.class文件),然后在运行期动态链接.这样,编译后的类文件中将包含有符号表,从而使得Java程序很容易被反编译.相信每一个Java开发人员,都曾经用过诸如Jad之类的反编译器,对Java的class 文件进行反编译,从而观察程序的结构与实现细节.如此一来,对于那些需要严格进行知识产权保护的Java应用,如何有效的保护客户的商业投资,是开发人员经常需要面对的问题.   于是

maven编译java代码报“非法字符: \65279 ”错误的解决方法

前段时间开发一个项目,使用maven进行编译时报“非法字符: \65279 ”,但是眼睛看怎么都正确的,文件转成utf-8编码还是报错. 最后没办法,暴力解决了这个问,步骤如下 1.把文件内容复制出来,我是复制到Sublime Text2里面. 2.删除原文件. 3.创建一个新的java文件,并将复制出去的文本粘贴回来.搞定. 最后查了一下,还是很多人遇到这个问题了,而且也有人解答了产生的原因. 这篇文章解答了产生的原因,也给出了另外两种解决方法 http://blog.163.com/[ema

java代码块的理解

最近在复习java基础,在看到java代码块的时候,忽然发现自己貌似对于java代码块一无所知,于是赶紧对着一些资料实战演练了一把. 对于java代码块,不难根据名称看出其实就是一些java语句的集合,以{}的形式出现,共有4中形式: 1.类的方法体 这是我们最常见的一种java代码块,形式如下: 1 public class Boke { 2 public void say(){ 3 System.out.println("我就是代码块的内容啦"); 4 } 5 } say的方法体{

Android的JS调用Java代码或使用了Javascript相关技术改如何混淆

http://www.androidren.com/index.php?qa=282&qa_1=android的js调用java代码或使用了javascript相关技术改如何混淆 Android 4.2开始 JS调用Java代码的时候必须加上@JavascriptInterface才能调用. 加上@JavascriptInterface之后就必须要考虑混淆时候的问题,如果混淆的时候把@JavascriptInterface搞丢了你的程序就无法调用了. 其实很简单,你只需要在混淆里面加上: -ke

5个常用Java代码混淆器 助你保护你的代码

从事Android App开发的都知道,一旦应用被破解,什么源代码.资源文件等都可能泄露,重要点有so文件的支付类.金融类应用等安全更是容易受到威胁!就Java语言编程,可以通过逆向工程反编译得到Java程序的源代码,这种反编译工具有jad .dex2jar .jdec .Dedexer 等.因此,为保护我们的劳动成果,尽可能给反编译人员制造障碍,我们可以用一些代码混淆器混淆代码,保护Java的类文件.然后,在混淆的基础上再做一层深层保护——加密.这个方法现在也比较流行,目前,有这方面技术的,有

APK中java代码反编译

Android APK中的Java代码可以被反编译到什么程度主要看APK的加密程度. 第一种情况:无混淆无加密无加壳.直接利用Dex2jar和JD-GUI可把源码从APK里抠出来,代码逻辑清晰,基本上做到可复用,只是资源文件的引用需要计算一下. 第二种情况:混淆.通常是利用Proguard做的防护.因为是对jar做的不可逆混淆(除非有mapping),因此不能还原成原来的代码.但是代码结构,代码逻辑一致,只要花长时间对代码进行梳理一样可找准核心代码,解密方法跟第一种一致. 第三种情况:加密.这里

Java代码质量监控工具Sonar安装

1.  代码质量七宗罪 Sonar是一个代码质量管理系统,它的帮助文档开篇明义,提出了代码质量的七宗罪,总结的比较到位,不妨一看: 1.        Bug和隐藏Bug(Bugs and Potential Bugs) 2.        违反编码规范(Coding Standards Breach) 3.        复制粘贴(Duplications) 4.        缺乏单元测试(Lack of Unit Tests) 5.        恶劣的复杂度分布(Bad Distribu

Lombok 安装、入门 - 消除冗长的 java 代码(转)

前言:    逛开源社区的时候无意发现的,用了一段时间,觉得还可以,特此推荐一下.    lombok 提供了简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 java 代码.特别是相对于 POJO,光说不做不是我的风格,先来看看吧. lombok 的官方网址:http://projectlombok.org/ lombok 其实到这里我就介绍完了,开个玩笑,其实官网上有 lombok 三分四十九秒的视频讲解,里面讲的也很清楚了,而且还有文档可以参考.在这里我就不扯太多,先来看一下 l

使用Maven构建Java项目

一.Maven是什么? Maven 是一个项目管理和构建自动化工具.Maven基于POM(Project object model),能够管理项目的构建.报表.文档等信息. 我们这里主要讲的Maven的项目构建功能.有了Maven,我们可以方便的管理Java项目的生命周期和依赖.通过定义一个POM文件,我们就可以自动的完成编译.测试.打包甚至发布等过程. 二.为什么要用Maven? 做过Java项目的童鞋都知道,一个项目中Java代码经常会依赖其他的jar包中的class,或者依赖其它的项目,手