参考资料
背景交代
因为 Android Studio 中的 Android Icon Creator 插件生成的图片路径还是在 drawable 之下,和同事纠结了一下还是决定将所有图片放在 mipmap 下面,所以就产生了动插件 jar 包的想法。
ROUND 1 - BytecodeViewer 2.9.8
很方便很强大的一个工具
在 Plugins 选项中,可以查看所有 String 和 修改 String 的功能。
但是在看 loading view 转啊转,重新打开文件的时候,并没有修改成功,卒
ROUND 2 - javac, javap
我们都知道,源文件 .java 通过 javac 变成字节码文件 .class, 那。。有没有一个命令是可以直接恢复 .class 文件变成 .java 文件呢?(呵呵,想得美
么,然后就找到了 javap
javap 可以查看 .class 文件的结构信息
就像这样
|
|
好了,然而这波哔并不能装,就看看就好了,卒
ROUND 3 - jclasslib
好,既然到这儿了,那么这次我们就一定能改成功了,事不过三嘛(笑死
找到我们想要修改的地方
这里我要修改的是 “Hello,world!”, 我们把它改成 “HAHAHA!”
因为 “Hello,world!” 是一个 String 而且是在 main 方法里面,所以我们只需要关注几个地方就好了:
- 常量池(Constant Pool)
- 方法名(Method#main)
去常量池找到目标资源
点击序号即可在常量池中定位到资源了,咦 String_info 好像是哦, 还可以点嘎, Utf8_info ,咦,完了…
嗯, 最后那个 Utf8_info 就是我们想要修改的目标资源了,记住序号 18
修改
123456789101112131415161718192021222324252627282930313233343536373839404142434445String filePath = "G:/HelloWorld.class";String targetStr = "Hello, world!";String replaceStr = "HAHAHA!";int targetStrIndex = 18;FileInputStream fInput = null;DataInput di = null;try {File mTargetFile = new File(filePath);fInput = new FileInputStream(mTargetFile.getAbsolutePath());di = new DataInputStream(fInput);ClassFile cf = new ClassFile();cf.read(di);CPInfo[] cps = cf.getConstantPool();for (int i = 0; i <= cps.length; i++) {if (i == targetStrIndex) {String mStr = cps[i].getVerbose();System.out.println("before: " + mStr);StringBuilder sb = new StringBuilder(mStr);sb.replace(0, targetStr.length(), replaceStr);mStr = sb.toString();System.out.println("after: " + mStr);ConstantUtf8Info mUtf8Info = (ConstantUtf8Info) cps[i];mUtf8Info.setString(mStr);cps[i] = mUtf8Info;}}cf.setConstantPool(cps);fInput.close();File f = new File(filePath);ClassFileWriter.writeToFile(f, cf);} catch (Exception e) {e.printStackTrace();}
运行结果