一款能将Java源码转成dexmaker代码的IDEA插件,方便开发和测试
去年年底在wanandroid每日一问:如何构造一个 hide interface 的实现类?问题中,残页同学的回答说,可以通过stub + compileOnly的方式用动态代理实现访问权限是package的接口。
我当时就想:用stub+动态代理还是有点麻烦,不是有个叫dexmaker的库可以在运行时动态生成dex吗?不知道能不能直接实现一个hidden的interface?
但我此前又没用过dexmaker,不知道代码要怎么写,觉得挺复杂的。 于是网上搜了一下生成dexmaker代码的工具,发现不但没有,就连dexmaker的相关文章也寥寥无几。
看了官方文档生成Fibonacci class的例子之后,忽然想到:这些代码都是有固定的规则和逻辑,那应该能做成一个自动生成的插件啊(实在不想自己动手写dexmaker代码)!之前不是有个IDEA插件可以生成ASM代码嘛?
于是反编译了那个ASM Bytecode Viewer插件,发现它的核心部分是直接使用ASM提供的jar包来实现的!原来ASM就有提供生成ASM代码的api!dexmaker为什么你就不提供一下这个东西啊!哈哈哈
接着又看了一下这个ASM的jar包,发现核心生成类ASMifier(这也是本项目的名字来源,它叫ASMifier,我就叫D(ex)M(aker)ifier吧,哈哈)继承了Printer,Printer结合ClassReader可以把class文件的指令都读取出来……
参照了ASMifier的做法,也弄了一个继承自Printer的类,并在重写的visitMethod
、visitInsn
等方法里按照dexmaker的规则去输出dexmaker代码……
插件安装后,在编辑器中右键菜单下方可看到 “View DexMaker Code” 选项:
或在主菜单 View 底部点击:
成功转换后会以Dialog的形式把结果弹出,直接复制到自己的代码里即可:
在线安装:
插件还在不断完善中,暂时未上传到JetBrain marketplace上。
本地安装:
到 releases 里下载最新的 DMifierPlugin.zip 后拖把它拖进IDE中并重启。
未实现的指令:
NOP、
POP2、
DUP_X1、
DUP_X2、
DUP2、
DUP2_X1、
DUP2_X2、
SWAP、
JSR、
MULTIANEWARRAY(创建多维数组)、
MONITORENTER、MONITOREXIT(synchronized语句)、
(try catch语句,dexmaker没有提供moveException方法)
不支持的指令:
INVOKEDYNAMIC(Dalvik 字节码没有对应的指令)、
TABLESWITCH、LOOKUPSWITCH(dexmaker没有提供相关api)
坑:
对了,这里还有个dexmaker的坑,就是if语句 if(a >= b)
,当a=0时,在生成dex之后,a和b的顺序会反过来,也就是变成了 if(b >= 0)
。 提了issue一周没人回答,才发现dexmaker在去年2月份就停止了更新!坑啊!!!
后续计划:
-
优化转换结果显示方式;
-
加入直接查看生成的dex文件的smali以及转成class后的代码;
- 0.1 提供基本转换功能。