点击蓝色字体“咖啡的小站”选择“设为星标”
及时获取咖啡最新的技术分享
图片来自摄影师:十一 | 专注儿童油画风摄影师
今年年初,咖啡在闲暇之余,制作了一款反编译小工具:SJD-GUI。美其名为反编译工具,实际是结合网上的小工具打包的一款软件。正愁分享些什么内容的时候,突然想到了这款已经被我尘封了很久的软件。其实里面也没有多少技术含量,分享的是一些思路,更多的是欢迎大家一起来参与讨论。
◆ ◆ ◆ ◆ ◆
01
背景
来源于早期咖啡在一次维护客户项目的过程中,从服务器上拉取了一个字节码文件,想反编译查看源代码。在客户机器上没有安装IDEA的情况下,第一时间想到的就是反编译工具:JD-GUI,一个橙色的小咖啡图标,相信很多同学都用过。绿色无需安装,功能完整,界面友好,成了大多数程序员反编译的首选。
不过今日在例行操作后,发现这款软件罢工了?
自动部署会报编译错误,排除;工具损坏?远程传送给同事试了一下JD-GUI反编译,同样的报错,继续排除;同事继续用idea,却能正常反编译,看来问题还是出在了这款工具上。
02
诊断
回想了一下,JD-GUI官方貌似很久之前就已经停止维护了,会不会对JDK后续版本支持不好?查看官网,果然问题出在这里:
因为项目所用jdk版本是java8,再追溯到代码源头,没错!就是Lambda的反编译支持问题。相信看到这里,可能会被不少同行笑话,如果你已经踩过坑,那么请忽略咖啡本节诊断过程的废话。
03
解忧
在用idea排除了项目问题之后,咖啡开始思考,还存不存在一款如JD-GUI好用但支持完整的反编译工具?最直接的方式就是开始谷歌,咖啡花了10到20分钟搜寻之后,发现并没有一款支持如JD-GUI友好的软件。友好支持JDK全版本反编译,界面不敢恭维;又如使用过程中莫名崩溃类的软件不胜枚举。最后一款反编译工具包,引起了咖啡的注意,名为:Procyon-decompiler.jar。
Procyon-Decompiler支持JDK1.8类的反编译,在很多方面做得非常不错:
另外它在反编译后能输出多种类型的结果,如Java源码、原始字节码、字节码AST。那么这款软件如何使用?这也是遗憾的地方。
进入CMD界面,输入命令:java –jar Procyon-decompiler.jar路径 .class文件路径。
演示代码:
public class DemoTest {
打开cmd界面,执行:
代码一多,查看起来是比较累眼睛的。鉴于轻微的强迫症,咱包装一下,写个小工具吧。
04
造车
不过用C写客户端程序我是不会的。咱玩java的, swing也是可以的。原理很简单,用swing图形界面结合后端cmd命令执行。后端程序,直接借助jdk基础类库rt下的Runtime类,即可输出cmd执行文本结果。
Runtime rtme = Runtime.getRuntime();Process pcRes = rtme.exec(cmdStr);
粗糙地画一个swing界面,这个怎么界面画就不贴出来了,不会的问度娘。
响应事件绑定后端cmd程序的执行即可。
@Overridepublic void actionPerformed(ActionEvent e) { // 绑定到选择文件,选择文件事件 String filename = ""; BufferedReader br = null; if (e.getSource().equals(button2)) { // 设定只能选择到文件 jfc.setFileSelectionMode(0); // 此句是打开文件选择器界面的触发语句 int state = jfc.showOpenDialog(null); // 撤销则返回 if (state == 1) { return; } else { // f为选择到的文件 File f = jfc.getSelectedFile(); filename = f.getName().replace(".class", ".java"); text2.setText(f.getAbsolutePath()); text2.setName(filename); try { long d1 = new Date().getTime(); Runtime rt = Runtime.getRuntime(); System.out.println(getClassPath()); String cmdStr = "cmd.exe /c java -jar "+getClassPath()+"\\procyon-decompiler-0.5.30.jar "+ text2.getText(); br = new BufferedReader(new InputStreamReader(rt.exec(cmdStr).getInputStream())); String line=null; StringBuffer b=new StringBuffer(); while ((line=br.readLine())!=null) { b.append(line+"\n"); } String javaCode = b.toString(); textField.setTextByColor(javaCode); } catch (Exception e1) { e1.printStackTrace(); } finally{ try { br.close(); } catch (IOException e1) { } } } }}
全部代码暂时就不贴了,最后分享出来。
执行效果:
看的不舒服,没关系我们再做一下关键字处理。列出所有关键字(可能不全,也是网上摘来的)。
/*** 所有关键字*/private final static String[] KEYS = new String[]{ "abstract","assert","boolean","break","byte","case","catch","char","class", "const","continue","default","do","double","else","enum","extends", "final","finally","float","for","goto","if","implements","import", "instanceof","int","interface","long","native","new","package", "private","protected","public","return","strictfp","short","static", "super","switch","synchronized","this","throw","throws","transient", "try","void","volatile","while" };
/** * 设置关键字颜色 * @param key * @param start * @param length * @return */private int setKeyColor(String key, int start, int length) { for (int i = 0; i < KEYS.length; i++) { int liIndex = key.indexOf(KEYS[i]); if (liIndex < 0) { continue; } int liLength = liIndex + KEYS[i].length(); if (liLength == key.length()) { //处理单独一个关键字的情况,例如:if else 等 if (liIndex == 0) { meDoc.setCharacterAttributes(start, KEYS[i].length(), keyAttr, false); } else {//处理关键字前面还有字符的情况,例如:)if ;else 等 char chTemp = key.charAt(liIndex - 1); if (isCharacter(chTemp)) { meDoc.setCharacterAttributes(start + liIndex, KEYS[i].length(), keyAttr, false); } } } else { //处理关键字后面还有字符的情况,例如:if( end;等 if (liIndex == 0) { char chTemp = key.charAt(KEYS[i].length()); if (isCharacter(chTemp)) { meDoc.setCharacterAttributes(start, KEYS[i].length(), keyAttr, false); } } else {//处理关键字前面和后面都有字符的情况,例如:)if( 等 char chTemp = key.charAt(liIndex - 1); char chTemp2 = key.charAt(liLength); if (isCharacter(chTemp) && isCharacter(chTemp2)) { meDoc.setCharacterAttributes(start + liIndex, KEYS[i].length(), keyAttr, false); } } } } return length + 1;}
最终效果如下:
看着舒服多了,虽然也只是个粗糙的包装工具,实用性也没有那么地强,不过解个燃眉之急还是阔以的。
05
尾声
感兴趣的同学可以自己动手试一下效果,下一节我们将介绍如何把当前的程序打包成一个随身带、随处执行的软件。如有疑问,可添加咖啡的私人微信号:shellery1988。
原创声明:原创文章,如需转载,请添加咖啡私人微信:shellery1988
备注:原创转载。咖啡看到了都会及时处理,感谢关注和支持!
Original url: Access
Created at: 2019-09-10 21:50:45
Category: default
Tags: none
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论