综述
Java从诞生以来,其基因就是开放精神,也正因此,其可以得到广泛爱好者的支持和奉献,最终很快发展壮大,以至于有今天之风光!但随着java的应用领域越来越广,特别是一些功能要发布到终端用户手中(如Android开发的app),有时候,公司为了商业技术的保密考虑,不希望这里面的一些核心代码能够被人破解(破解之后,甚至可以被简单改改就发布出去,说严重点,就可能会扰乱公司的正常软件的市场行为),这时候就要求这些java代码不能够被反编译。

这里要先说一下反编译的现象。因为java一直秉持着开放共享的理念,所以大家也都知道,我们一般共享一个自己写的jar包时,同时会共享一个对应的source包。但这些依然与反编译没有什么关系,但java的共享理念,不只是建议我们这样做,而且它自己也在底层上“强迫”我们这么做!在java写的.java文件后,使用javac编译成class文件,在编译的过程,不像C/C++或C#那样编译时进行加密或混淆,它是直接对其进行符号化、标记化的编译处理,于是,也产生了一个逆向工程的问题:可以根据class文件反向解析成原来的java文件!这就是反编译的由来。

但很多时候,有些公司出于如上述的原因考虑时,真的不希望自己写的代码被别人反编译,尤其是那些收费的app或桌面软件(甚至还有一些j2ee的wen项目)!这时候,防止反编译就成了必然!但前面也说过了,因为开放理念的原因,class是可以被反编译的,那现在有这样的需求之后,有哪些方式可以做到防止反编译呢?经过研究java源代码并进行了一些技术实现(结果发现,以前都有人想到过,所以在对应章节的时候,我会贴出一些写得比较细的文章,而我就简单阐述一下,也算偷个懒吧),我总共整理出以下这几种方式:

代码混淆
这种方式的做法正如其名,是把代码打乱,并掺入一些随机或特殊的字符,让代码的可读性大大降低,“曲线救国”似的达到所谓的加密。其实,其本质就是打乱代码的顺序、将各类符号(如类名、方法名、属性名)进行随机或乱命名,使其无意义,让人读代码时很累,进而让人乍一看,以为这些代码是加过密的!

由其实现方式上可知,其实现原理只是扰乱正常的代码可读性,并不是真正的加密,如果一个人的耐心很好,依然可以理出整个程序在做什么,更何况,一个应用中,其核心代码才是人们想去了解的,所以大大缩小了代码阅读的范围!

当然,这种方式的存在,而且还比较流行,其原因在于,基本能防范一些技术人员进行反编译(比如说我,让我破解一个混淆的代码,我宁愿自己重写一个了)!而且其实现较为简单,对项目的代码又无开发上的侵入性。目前业界也有较多这类工具,有商用的,也有免费的,目前比较流行的免费的是:proguard(我现象临时用的就是这个)。

上面说了,这种方式其实并不是真正加密代码,其实代码还是能够被人反编译(有人可能说,使用proguard中的optimize选项,可以从字节流层面更改代码,甚至可以让JD这些反编译软件可以无法得到内容。说得有点道理,但有两个问题:1、使用optimize对JDK及环境要求较高,容易造成混淆后的代码无法正常运行;2、这种方式其实还是混淆,JD反编译有点问题,可以有更强悍的工具,矛盾哲学在哪儿都是存在的_)。那如何能做到我的class代码无法被人反编译呢?那就需要我们下面的“加密class”!

加密class
在说加密class之前,我们要先了解一些java的基本概念,如:ClassLoader。做java的人已经或者以后会知道,java程序的运行,是类中的逻辑在JVM中运行,而类又是怎么加载到JVM中的呢(JVM内幕之类的,不在本文中阐述,所以点到为止)?答案是:ClassLoader。JVM在启动时是如何初始化整个环境的,有哪些ClassLoader及作用是什么,大家可以自己问度娘,也不在本文中讨论。

让我们从最常见的代码开始,揭开一下ClassLoader的一点点面纱!看下面的代码:

Java代码  收藏代码
public class Demo{  public static void main(String[] args){  System.out.println(“hello world!”);  }  }

上面这段代码,大家都认识。但我要问的是:如果我们使用javac对其进行编译,然后使用java使其运行(为什么不在Eclipse中使用Run as功能呢?因为Eclipse帮我们封闭,从而简化了太多东西,使我们忽略了太多的底层细节,只有从原始的操作上,我们才能看到本质),那么,它是怎么加载到JVM中的?答案是:通过AppClassLoader加载的,如果不相信的话,可以输出一下System.out.println(Thread.currentThrea().getContextLoader());看看。

那又有一个新的问题产生了:ClassLoader又是怎样加载class的呢?其实,AppClassLoader继承自java.lang.ClassLoader类,所以,基本操作都在这个类里面,让我们直接看下面这段核心代码吧:

看看这个方法中的逻辑,非常简单,先从内存中找,如果没有,则从父级或根先找,如果没找到,则再从自己的方法里面找!那findClass里面是什么样的呢?很不幸,这个方法是个抽象(abstract)的,也就是使用什么方式加载,由程序使用ClassLoader自己决定!这就给我们留下了巨大的“”!让我们看一下非常常见的一个ClassLoader的实现,那就是URLClassLoader(几乎所有的j2ee的web项目的容器使用的ClassLoader都是继承自它),让我们看一下它的findClass的实现:

这个方法里面的逻辑也很简单,从定义的ucp(就是各个jar包或class文件的具体路径)中读取指定的class文件的信息(如字节流之类),然后交给defineClass定义到JVM中,让我们继续看一下这个方法的核心部分:

看到这里,已经没有必要再往下面看了(再往下就是native方法了,这是一个重大伏笔哦),我们要做的手脚就在这里!

手脚怎么做呢?很简单,上面的代码逻辑告诉我们,ClassLoader只是拿到class文件中的内容byte[],然后交给JVM初始化!于是我们的逻辑就简单了:只要在交给JVM时是正确的class文件就行了,在这之前是什么样子无所谓!所以,我们的加密的整个逻辑就是:

在编译代码时(如使用ant或maven),使用插件将代码进行加密(加密方式自己选),将class文件里面的内容读取成byte[],然后进行加密后再写回到class文件(这时候class文件里面的内容不是标准的class,无法被反编译了)
在启动项目代码时,指定使用我们自定义的ClassLoader就行了,而自定义的部分,主要就是在这里做解密工作!
如此,搞定!以上的做法比较完整的阐述,可以仔细阅读一下这篇文章:http://www.ibm.com/developerworks/cn/java/l-secureclass/文章中的介绍。

通过这个方法貌似可以解决代码反编译的问题了!错!这里有一个巨大的坑!因为我们自定义的ClassLoader是不能加密的,要不然JVM不认识,就全歇菜了!如果我来反编译,呵呵,我只要反编译一下这个自定义的ClassLoader,然后把里面解密后的内容写到指定的文件中保存下来,再把这个加了逻辑的自定义ClassLoader放回去运行,你猜结果会怎样?没错,你会想死!因为你好不容易想出来的加密算法,结果人家根本不需要破解,直接就绕过去了!

现在,让我们总结一下这个方法的优缺点:实现方式简单有效,同时对代码几乎没有侵入性,不影响正常开发与发布。缺点也很明显,就是很容易被人破解!

当然啦,关于缺点问题,你也可以这么干:先对所有代码进行混淆、再进行加密,保证:1、不容易找到我们自定义的那个ClassLoader;2、就算找到了,破解了,代码可读性还是很差,让你看得吐血!

嗯,我觉得这个方法很好,我自己也差点被这个想法感动了,但是,作为一个严谨的程序员,我真的不愿意留下一个隐患在这里!所以,我继续思索!

高级加密class
前面我们说过有个伏笔来着,还记得吧?没错,就是那个native!native定义的方法是什么方法?就是我们传说中的JNI调用!前面介绍过的有一篇文章中提到过,其实jvm的真实身份并不是java,而是c++写的jvm.dll(windows版本下),java与dll文件的调用就是通过JNI实现的!于是,我们就可以这样想:JNI可以调用第三方语言的类库,那么,我们可不可以把解密与装载使用第三方语言写(如C++,因为它们生成的库是不好反编译的),这样它可以把解密出来的class内容直接调jvm.dll的加载接口进行初始化成class,再返回给我们的ClassLoader?这样,我们自定义的ClassLoader只要使用JNI调用这个第三方语言写的组件,整个解密过程,都在黑盒中进行,别人就无从破解了!

嗯,这个方法真的很不错的!但也有两个小问题:1.使用第三方语言写,得会第三方语言,我说的会,是指很溜!2.对于不同的操作系统,甚至同一操作系统不同的版本,都可能要有差异化的代码生成对应环境下的组件(如window下是exe,linux是so等)!如果你不在乎这两个问题,我觉得,这个方式真的挺不错的。但对于我来说,我的信条是,越复杂的方式越容易出错!我个人比较崇尚简洁的美,所以,这个方法我不会轻易使用!

更改JVM
看到这个标题,我想你可能会震惊。是的,你没看错,做为一个程序员,是应该要具有怀疑一切、敢想敢做的信念。如果你有意留心的话,你会发现JVM版本在业界其实也有好几个版本的,如:Sun公司的、IBM的、Apache的、Google的……

所以,不要阻碍自己的想象力,现在没有这个能力,并不代表不可能。所以,我想到,如果我把jvm改了,在里面对加载的类进行解密,那不就可以了吗?我在设计构思过程中,突然发现:人老了就是容易糊涂!前面使用第三方语言实现解密的两个问题,正好也是更改JVM要面对的两个问题,而且还有一个更大的问题:这个JVM就得跟着这个项目到处走啊!有一个类似的思路是这样:

http://wenku.baidu.com/link?url=T0LOwOI5DDFRoFGJp_vzwq8x6OADAcnHcNBOFqij5jz7Rvt1wsjLe8Qa2sJFUBQha88A5csGqDH5yXIjWVV4i54x-iXtYpPSO9kJtQLhvNy

于是,我把构思与设计从头又想了想,终于……放弃了!

设想
前面可以说,我能想到的方式,我都想到了,都不能令我满意。于是我在想,有没有一个让我感觉代价又小,但却无隐患的方式呢?

我现在还没想出来,只能待续……

(不日即有答案,因为进度日期将近……等有答案,一定补上,与大家讨论,或者大家给些意见,谢谢!)

总结
经过对java不断深入研究,以及多年来对java知识的积累,最重要的是,一种遇到困难时执着向前的精神,最终使得问题的解决越来越完善!虽然走过弯路,但每条弯路上都有许多收获,就像我曾经做得的分享里面说的:同一个现象,不同的视野将得到不同的结果!如何提升自己视野?就在于平时不断的自我追求和强烈的求知欲!

java如何防止反编译相关推荐

  1. 安装 java decompiler_Eclipse离线安装Java Decompiler插件(反编译)

    Java Decompiler是Java语言的反编译工具,具体介绍见博客Java Decompiler(Java反编译工具) 1.下载插件 Eclipe的Java Decompiler插件名为JD-E ...

  2. java class文件反编译 去掉无用注释

    java class文件反编译之后 有一些没有用的注释 在myEclipse中使用正则表达式 /\*(.*)\*/

  3. Java class 文件反编译工具JD-GUI下载安装使用教程(好用)

    多少个日日夜夜上线系统.都会有明明我改成了最新代码咋没变呢这咋整,看看反编译后的文件吧.每次看完都哦的 豁然开朗. 简介: JD-GUI是java class反编译软件上线的时候很有用.开发这么多年找 ...

  4. 一些防止 Java 代码被反编译的方法

    欢迎关注方志朋的博客,回复"666"获面试宝典 由于Java字节码的抽象级别较高,因此它们较容易被反编译.本节介绍了几种常用的方法,用于保护Java字节码不被反编译.通常,这些方法 ...

  5. 面试被问 | 防止 Java 代码被反编译的方法有几种?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 后台回复"k8s",可领取k8s资料 由于Java字节 ...

  6. Java字节码反编译工具

    jd-gui-0.3.3.windows.zip是一个JAVA字节码(.class文件)反编译的工具, 试了一下感觉挺好用的的.下载地址: http://ishare.iask.sina.com.cn ...

  7. java字节码反编译_javap 反编译 java 字节码文件

    概述: javap是 Java class文件分解器,可以反编译,也可以查看java编译器生成的字节码,从而对代码内部的执行逻辑进行分析. 语法: 把java文件编译为class文件:javac  T ...

  8. java中如何反编译class文件

    作为一个软件开发人员,在自学的成长道路上,不可避免的会借鉴别人开发完成的功能实现方法,js/css/html可以通过浏览器直接捕获,没有源码的能拿到calss文件也是一件幸事,那么如何查看class文 ...

  9. java反射和反编译

    目录 反射机制与什么用 反射机制相关的类 获取类的字节码三种方式 1 通过Class类的静态方法获取字节码 2 通过类的getClass()方法获取 3 通过class属性获取 通过反射创建对象 获取 ...

  10. 将exe4j打包的java exe程序反编译过程

    开始,我用了http://blog.csdn.net/lanximu/article/details/16879545的方法,但十六进制文件看着有乱码,试着截了几次进行压缩,但都不对,不管是用ultr ...

最新文章

  1. 使用Comet4j实现消息推送
  2. 中信国健临床通讯2011年7月期目录
  3. Ubuntu中python调用SimpleITK来显示图像
  4. Git(11)-cherry-pick、reset、rebase
  5. 高级语言程序设计c 华南理工,华南理工大学高级语言程序设计(C)期末练习题
  6. Python+matplotlib设置y轴标签距离、位置、竖排
  7. 机器视觉:工业镜头专业词汇中英文详解
  8. python字符串及基本运算
  9. 基于javaweb+jsp的运动会体育比赛管理系统(带报告文档)
  10. 店铺淘口令怎么生成, 怎么生成店铺淘口令
  11. 解决 CDH6.3.1 安装HDFS时出现{{CMF_CONF_DIR}}/redaction-rules.json (No such file or directory)错误
  12. java中的match函数_js 正则表达式中的match函数
  13. 深度学习笔记第一门课第三周:浅层神经网络
  14. 关于计算机物联网的文章,物联网认识论文3000字_关于物联网认识论文3000字_物联网导论论文3000字...
  15. 移动机顶盒搭建网页服务器,超级简单搭建自己的私人影视库
  16. 王者荣耀主播(孤王)过度劳累猝死 曾被誉为国服第一辅助
  17. 威联通NAS提示“拒绝了我们的连接请求”的解决办法
  18. 公链分析报告(2)--EOS
  19. 大商创 常见问题 mysql_大商创手机端出现404的官方解决方案
  20. HDU 4123 树状DP+RMQ

热门文章

  1. 华信IT教育201611第一篇博客
  2. 2019年报表工具软件怎么选
  3. 【Appium】使用模拟器实现有道云App的安装卸载
  4. 黑客公布从Medibank窃取的50万用户数据;苹果招募大量神经渲染研究员;Slack 的CEO将卸任 | 每日大事件...
  5. 2020.01.11 【ABAP随笔】获取标准报表数据(MB52)数据进行客制ALV
  6. 一个封装的BeanCopier工具类
  7. Tensorflow2.0:CNN 解决凯斯西储大学轴承数据集的分类问题
  8. linux 读取飞信信息,Linux下安装飞信客户端(OpenFetion)
  9. 如何用Jmeter上传下载文件
  10. 送福利啦!PaddleCV方向精选项目合集