java反编译有什么缺陷,Java中Jar包为什么能轻易就给反编译了
本篇文章给大家谈谈java反编译有什么缺陷,以及Java中Jar包为什么能轻易就给反编译了对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。
什么是Java代码的编译与反编译
Java代码的编译与反编译
2017-02-21Hollis数盟
一、什么是编译
1、利用编译程序从源语言编写的源程序产生目标程序的过程。
2、用编译程序产生目标程序的动作。编译就是把高级语言变成计算机可以识别的2进制语言,计算机只认识1和0,编译程序把人们熟悉的语言换成2进制的。编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;语义检查和中间代码生成;代码优化;目标代码生成。主要是进行词法分析和语法分析,又称为源程序分析,分析过程中发现有语法错误,给出提示信息。
二、什么是反编译
计算机软件反向工程(Reverseengineering)也称为计算机软件还原工程,是指通过对他人软件的目标程序(可执行程序)进行“逆向分析、研究”工作,以推导出他人的软件产品所使用的思路、原理、结构、算法、处理过程、运行方法等设计要素,某些特定情况下可能推导出源代码。反编译作为自己开发软件时的参考,或者直接用于自己的软件产品中。
三、Java类的编译与反编译
我们在最初学习Java的时候,会接触到两个命令:javac和java,那个时候我们就知道,javac是用来编译Java类的,就是将我们写好的helloworld.java文件编译成helloworld.class文件。
class文件打破了C或者C++等语言所遵循的传统,使用这些传统语言写的程序通常首先被编译,然后被连接成单独的、专门支持特定硬件平台和操作系统的二进制文件。通常情况下,一个平台上的二进制可执行文件不能在其他平台上工作。而Javaclass文件是可以运行在任何支持Java虚拟机的硬件平台和操作系统上的二进制文件。
那么反编译呢,就是通过helloworld.class文件得到java文件(或者说是程序员能看懂的Java文件)
四、什么时候会用到反编译
1、我们只有一个类的class文件,但是我们又看不懂Java的class文件,那么我们可以把它反编译成我们可以看得懂的文件。
2、学习Java过程中,JDK的每个版本都会加入越来越多的语法糖,有些时候我们想知道Java一些实现细节,我们可以借助反编译。
五、反编译工具
1、javap
2、Jad:官网(墙裂推荐)
客户端:
可以在官网下载可执行文件,找到对应的操作系统的对应版本,然后进行安装使用。
因为我使用的是linux操作系统,所以我下载的是Linux版本的工具,这个工具下载好之后会有一个执行文件,只要在执行文件所在目录执行./jadhelloworld.class就会在当前目录下生成helloworld.jad文件,该文件里就是我们很熟悉的Java代码
Eclipse插件:
下载地址在官网下载插件的jar包,然后将jar包放到eclipse的plugins目录下‘在打开Eclipse,Eclipse->Window->Preferences->Java,此时你会发现会比原来多了一个JadClipse的选项,单击,在Pathtodecompiler中输入你刚才放置jad.exe的位置,也可以制定临时文件的目录。当然在JadClipse下还有一些子选项,如Debug,Directives等,按照默认配置即可。基本配置完毕后,我们可以查看一下class文件的默认打开方式,Eclipse->Window->Preferences->General->Editors->FileAssociations我们可以看到class文件的打开方式有两个,JadClipse和Eclipse自带的ClassFileViewer,而JadClipse是默认的。全部配置完成,下面我们可以查看源码了,选择需要查看的类,按F3即可查看源码
Java中Jar包为什么能轻易就给反编译了
java中jar包轻易的被反编译是由于java的特性决定的。java中的jar包的实质内容是java源代码编译后的.class文件,由于java的面向对象特性和java的反射技术,可以很容易的通过对.class文件进行反射来得到java的源代码,也就是反编译!对于java的反编译,并不是所有内容都会反编译出来,java源文件中的注释、泛型等内容在经过编译和反编译之后会丢失。
防止JAVA代码被反编译的方法
我们都知道JAVA是一种解析型语言这就决定JAVA文件编译后不是机器码而是一个字节码文件也就是CLASS文件而这样的文件是存在规律的经过反编译工具是可以还原回来的例如Decafe FrontEnd YingJAD和Jode等等软件下面是《Nokia中Short数组转换算法》
类中Main函数的ByteCode
ldc#
invokestatic#
astore_
return
其源代码是 short [] pixels= parseImage(/ef s png);
我们通过反编译工具是可以还原出以上源代码的而通过简单的分析我们也能自己写出源代码的
JAVA手机网[]第一行 ldc#
ldc为虚拟机的指令作用是压入常量池的项形式如下
ldc index
这个index就是上面的也就是在常量池中的有效索引当我们去看常量池的时候我们就会找到index为的值为String_info里面存了/ef s png
所以这行的意思就是把/ef s pn作为一个String存在常量池中其有效索引为
第二行 invokestatic#
invokestatic为虚拟机指令作用是调用类(static)方法形式如下
invokestatic indexbyte indexbyte
其中indexbyte和indexbyte必须是在常量池中的有效索引而是指向的类型必须有Methodref标记对类名方法名和方法的描述符的引用
所以当我们看常量池中索引为的地方我们就会得到以下信息
Class Name: cp_info#
Name Type: cp_info#
和都是常量池中的有效索引值就是右边<>中的值再往下跟踪我就不多说了有兴趣的朋友可以去JAVA虚拟机规范
这里我简单介绍一下parseImage(Ljava/lang/String;)[S的意思
JAVA手机网[]这就是parseImage这个函数的运行我们反过来看看parseImage的原型就明白了
short [] parseImage(String)
那么Ljava/lang/String;就是说需要传入一个String对象而为什么前面要有一个L呢这是JAVA虚拟机用来表示这是一个Object如果是基本类型这里就不需要有L了然后返回为short的一维数组也就是对应的[S是不是很有意思 S对应着Short类型而 [对应一维数组那有些朋友要问了两维呢那就 [[呵呵是不是很有意思
好了调用了函数返回的值要保存下来吧那么就是第三行要做的事情了
第三行 astore_
呵呵很简单的但是却有文章也是比较容易混乱的地方
astore_为虚拟机指令作用为将当前reference存储到局部变量中去而必须是对当前框架的局部变量的有效索引打个比方可能我们这个函数中可能还要用到这个局部变量我们可以通过来找到它例如调用虚拟机指令
aload_就能得到该值
第四行 return
同样的 return也是虚拟机指令了它的作用为从方法返回void
这里也就是退出main函数
ok终于啰嗦完毕了有些朋友可能要问这么复杂才四行就说这么多呵呵可能是我这人废话过多当然如果你熟悉了一点就能看懂了通过肉眼就可以反编译程序了目前所有的反编译工具都无法做到完美反编译在有问题的地方还需要人去修正
好了说了半天如何反编译我们就来看看如果在你的程序如果防止别人来反编译好不容易写好的程序被人反编译了多郁闷哈哈工欲善其事必先利其器这句话用对了吗?
什么混淆等等的方法我就不说了我这里主要是要说一种通过添加代码来在某种程度来避免当前流行的反编译工具对你的代码进行反编译
方案一
首先要添加一个参数为Exception类型的函数例如这样
public static void Fake(Exception e)
{
JAVA手机网[] e toString();
}
一定要有e toString();因为要防止你的混淆器把无用的代码过滤
然后在每个类中调用这个函数放在try catch(Exception e)中的catch里面例如
try
JAVA手机网[]{
}
catch(Exception e)
{
Fake(e);
}
请注意一定要放在catch才有用其他地方无用
方案二
如果以上方法还不够专业我们再来一个呵呵~
同样的我们定义一个类这个类叫做AntiCrack名字好像有点大代码如下
public class AntiCrack
{
private AntiCrack()
{
}
public static Throwable Fake(Throwable throwable Throwable throwable)
{
try
{
throwable getClass() getMethod( initCause new Class[]{
JAVA手机网[] java lang Throwable class
}) invoke(throwable new Object[]{
throwable
});
}
catch(Exception exception){}
return throwable;
}
}
同样的我们在catch里面调用该函数例如如下
try
{
//your code here
}
catch(IOException ioexception)
{
IllegalArgumentException illegalargumentexception= new IllegalArgumentException(ioexception toString());
AntiCrack fake(illegalargumentexception ioexception);
throw illegalargumentexception;
}
或者也可以这样
public class AntiException extends Exception
{
public AntiException()
{
}
public AntiException(String s)
{
super(s);
}
public AntiException(String s Throwable throwable)
{
super(s);
AntiCrack fake(this throwable);
}
}
JAVA手机网[]然后在你的程序里面
try
{
}
catch(IoException e)
{
throw new AntiException(ioexception toString() ioexception);
}
当采用以上方式后任何类只要调用了该函数生成的class反编译后出错得不到结果
Decafe FrontEnd和YingJAD反编译时都有exception然后无法进行下去大家可以多测试变得反编译工具建议推荐用第二个方法
lishixinzhi/Article/program/Java/hx/201311/25765Java反编译工具有什么作用
就是把经过java文件编译后的可执行的class文件再反编译为java文件,因为经过编译的class文件是不可阅读的!但是由于java文件一般都不是单独运行的,会有类之间的相互调用,所以反编译工具反编译后只能大体上还原原来java文件,而不能完全还原,特别是一些变量的取值,定义等..
关于java反编译有什么缺陷和Java中Jar包为什么能轻易就给反编译了的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。