在项目上线之前需要通过ProGuard来对java的class进行混淆,以避免反编译方式,来保护自己的代码。ProGuard网上有很多资料,可以参考:http://blog.csdn.net/zhangdaiscott/article/details/45368261。在此,记录扰码可执行JAR包出现的问题,已经相关的解决方式。

1、引用第三方库的处理方式

引用第三方库,应避免修改第三方库的类名和public的方法、参数,否则在proguard回报很多warning,而执行失败。在Eclipse打包为可执行jar包时有以下的几个选择。

Extract方式是缺省的方式,会将第三方jar包解压成为具体的*.class ,然后和我们自己的*.class一起封装成为jar。Proguard会对所有class进行扰码,因此包括了第三方jar包。

最直接的方式就是让第三方jar包不参与proguard的混淆,因此我们可以选择余下两种方式,这里我选择了Package方式。我们用7Zip对jar包进行解压,会看到第三方jar包仍以jar包的方式存在。

2、可执行main要保留

我们需要保留jar包中的资源,特别是MANIFEST.MF文件,下面是这个文件的例子:

Rsrc-Class-Path: ./ log4j-core-2.4.1.jar log4j-api-2.4.1.jar gson-2.4. jar  mysql-connector-java-5.1.37.jar

Class-Path: .

Rsrc-Main-Class: MyPackage.App

Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader

这里设计两个具有Main的可执行类MyPackage.App,和org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader(顾名思义,load第三方库的)。我们必须确保能够找到这两个类的main,也就是这两个类的全名(包名和类名)以及mian的方法名字都必须保留正确。增加一下配置即可:

-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF

-whyareyoukeeping class *

-keep public class MyPackage.App {

    public static void main(java.lang.String[]);

}

-keep public class org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader {

    public static void main(java.lang.String[]);

}

对应与GUI中,如下几图:

有些参数是可以调整的,例如可以不选择Keep parameter

3、关于Gson

如果我们采用Gson来进行Json的处理,由于Gson和类中定义的成员名字有关,如果对这些名字进行混淆,则无法正确进行Json的解析,有两种方法处理:

1)在上图中右下方的“Keep additional names and class membe names”中选择相关的类和成员。一般这些成员都是private的。

2)更合适的方式如下,在代码中加入@SerializedName

    @SerializedName("clientName")

    private String clientName;

    @SerializedName("ServerName")

    private String ServerName;

此外,对于要封装成JSON字符串的属性,必须提供getter方法,例如上面如果不提供getClientName,则json字符串中没有该属性。对应的,如果进行解析,则必须提供setter方法。

出现一个奇怪的现象待查。如果定义一个数组Vector<String> urls,当然也给出@SerializedName("urls")。如果我们将此定义在继承类,在运行的时候会报错,如下所示。需要将此定义在基类来解决,有些奇怪,先记录下来

  1. 错误:java.lang.IllegalArgumentException: class c.d declares multiple JSON fields named h
  2. java.lang.IllegalArgumentException: class c.d declares multiple JSON fields named h
  3. at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:167) ~[gson-2.4.jar:?]
  4. at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:97) ~[gson-2.4.jar:?]
  5. at com.google.gson.Gson.getAdapter(Gson.java:360) ~[gson-2.4.jar:?]
  6. at com.google.gson.internal.bind.ArrayTypeAdapter$1.create(ArrayTypeAdapter.java:48) ~[gson-2.4.jar:?]
  7. at com.google.gson.Gson.getAdapter(Gson.java:360) ~[gson-2.4.jar:?]
  8. at com.google.gson.Gson.fromJson(Gson.java:813) ~[gson-2.4.jar:?]
  9. at com.google.gson.Gson.fromJson(Gson.java:752) ~[gson-2.4.jar:?]
错误:java.lang.IllegalArgumentException: class c.d declares multiple JSON fields named h
java.lang.IllegalArgumentException: class c.d declares multiple JSON fields named h
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:167) ~[gson-2.4.jar:?]
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:97) ~[gson-2.4.jar:?]
at com.google.gson.Gson.getAdapter(Gson.java:360) ~[gson-2.4.jar:?]
at com.google.gson.internal.bind.ArrayTypeAdapter$1.create(ArrayTypeAdapter.java:48) ~[gson-2.4.jar:?]
at com.google.gson.Gson.getAdapter(Gson.java:360) ~[gson-2.4.jar:?]
at com.google.gson.Gson.fromJson(Gson.java:813) ~[gson-2.4.jar:?]
at com.google.gson.Gson.fromJson(Gson.java:752) ~[gson-2.4.jar:?]

相关链接:开发日志

【Developer Log】ProGuard扰码可执行JAR包的更多相关文章

  1. Spring Boot 怎么打一个可执行 Jar 包?

    传统的 Java 应用程序都需要打一个 war 包,并到到 Tomcat webapps 目录下运行. Java 支持打 Jar 包,但没有提供一个标准的方式在一个 Jar 包内再加载嵌入别的 Jar ...

  2. 使用eclipse创建java程序可执行jar包

    一.eclipse中,在要打成jar包的项目名上右击,出现如下弹出框,选择“export”: 二.在接下来出现的界面中点击“jar file”,然后next: 三.在接下来出现的界面中,如图所示勾选上 ...

  3. 使用原生Java代码生成可执行Jar包

    最近想做一个功能,就是把我们编译后的字节码及其资源文件打包成一个可执行的jar包,在装有jre的机器上双击就能运行. 首先是我们需要选择哪些字节码和文件需要打包到文件中,这个我们用JFileChoos ...

  4. 将 Spring boot 项目打成可执行Jar包,及相关注意事项(main-class、缺少 xsd、重复打包依赖)

    最近在看 spring boot 的东西,觉得很方便,很好用.对于一个简单的REST服务,都不要自己部署Tomcat了,直接在 IDE 里 run 一个包含 main 函数的主类就可以了. 但是,转念 ...

  5. SpringBoot小技巧:修改java可执行jar包内容

    SpringBoot小技巧:修改java可执行jar包内容 情景描述 在生产环境中,有时候我们发现了个小bug,开发迅速修改代码后,很多时候我们不得不重新发布一个新的可执行jar包上去替换掉.但是这样 ...

  6. java 执行 jar 包中的 main 方法

    java 执行 jar 包中的 main 方法 通过 OneJar 或 Maven 打包后 jar 文件,用命令: java -jar ****.jar执行后总是运行指定的主方法,如果 jar 中有多 ...

  7. 用Intellij打可执行jar包

    1.添加maven-assembly-plugin和maven-dependency-plugin assembly:用于打可执行jar包 dependency: 导出依赖包 <plugin&g ...

  8. Maven打包可执行Jar包方式

    第一步:pom.xm中的build标签下加入maven插件配置,打包生成可执行jar包方式Maven中的打包方式更换为 <packaging>jar</packaging> b ...

  9. NetBeans IDE 7.4 Beta版本build JavaFX时生成的可执行jar包执行时找不到依赖的jar包

    现象,执行时抛出java.lang.ClassNotFoundException异常: Executing E:\secondegg\secondegg-reversi\dist\run8022211 ...

随机推荐

  1. java事件处理机制(自定义事件)

    java中的事件机制的参与者有3种角色: 1.event object:事件状态对象,用于listener的相应的方法之中,作为参数,一般存在与listerner的方法之中 2.event sourc ...

  2. mysql中 groupby分组

    引用自http://www.cnblogs.com/mo-beifeng/archive/2012/02/07/2341886.html#2341105 --按某一字段分组取最大(小)值所在行的数据 ...

  3. [Swift通天遁地]五、高级扩展-(1)快速检测设备属性:版本、类型、屏幕尺寸

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  4. hadoop一主一从部署(1)

    一.安装前说明 主机IP:192.168.132.128 从机IP:192.168.132.129 1. 所有的安装包我放在了/root/这个目录下,你要根据自己情况去修改,这点必须注意 2. 采用的 ...

  5. python django简单操作

    准备: pip3 install  django==1.10.3 cmd django-admin startproject  guest  创建一个guest的项目 cd guest manage. ...

  6. 【Leetcode146】LRU Cache

    问题描述: 设计一个LRU Cache . LRU cache 有两个操作函数. 1.get(key). 返回cache 中的key对应的 val 值: 2.set(key, value). 用伪代码 ...

  7. Kibana里No Marvel Data Found问题解决(图文详解)

    问题详情 http://192.168.80.145:5601/app/marvel#/no-data?_g=(refreshInterval:(display:'10%20seconds',paus ...

  8. SQL Sever语言 事务

    事务:保障流程的完整执行保证程序某些程序在运行时同时成功同时失败,保证程序的安全性 begin tran --在流程开始的位置加 --此处写SQL语句 if @@error>0 --ERRORS ...

  9. Java Controller下兼容xls和xlsx且可识别合并单元格的excel导入功能

    1.工具类,读取单元格数据的时候,如果当前单元格是合并单元格,会自动读取合并单元格的值 package com.shjh.core.util; import java.io.IOException; ...

  10. NSNotificationCenter 的使用详解

    通常我们在 iOS 中发生什么事件时该做什么是由 Delegate 实现的,例如 View 加载完后会触发 viewDidLoad.Apple 还为我们提供了另一种通知响应方式,那就是 NSNotif ...