在预编译的类文件(Java)上重命名导入



有什么问题?我是《我的世界》服务器管理员/服务器主机/插件开发者,但发现每次核心游戏新发行时都要更新我自己的插件是件非常烦人的事。事情并不总是这样的,我曾经在20个版本中使用插件而没有出现问题。你可以想象,每个月必须坐下来更新40个插件,这是我生活中不必要的烦恼,因为我过去从来没有这样做过。

是什么导致了这个问题?在每个新版本中,它们要求您在编译的jar文件中使用不同的导入,从而强制破坏任何过时的(但可能仍然有效的)jar文件。相信我。我可以阅读错误日志,知道什么时候我需要出去下载一个新的更新。我现在不需要保护自己。这只是一场比赛,我对它没有太多的期望。

那么我该怎么做呢?为此,我想做一个简单的程序,自动更新我所有的插件。(插件以打包的.jar文件的形式出现。)它需要做以下事情:

  1. 获取X_Folder
  2. 中所有jar文件的列表
  3. 对于每个jar文件,获得所有类的封装。
  4. 对于每个类文件,搜索Y_STRING的任何实例并将其替换为Z_STRING。
  5. 确保所有的东西都被正确地放回jar文件中。

问题吗?我如何编写类文件编辑方法?我都不知道该怎么开口。

免责声明抱歉,听起来好像我还没开始做这件事。我只是没有任何字节码操作的经验。我已经看到了一些示例,但还没有看到任何关于重命名导入的内容。希望这里有人能帮助我。谢谢你!

  1. 获取X_Folder
  2. 中所有jar文件的列表
  3. 对于每个jar文件,获得所有类的封装。
  4. 对于每个类文件,搜索Y_STRING的任何实例并将其替换为Z_STRING。
  5. 确保所有的东西都被正确地放回jar文件中。

1)这是基本的文件操作。查看java.io.File#listFiles()或其过载。

2) JAR文件是具有特定内容的ZIP文件。研究java.util.jar.JarFilejava.util.zip.ZipInputStream;遍历它的条目(JarFile#entries())并解压(JarFile#getInputStream(ZipEntry))中的每个类文件。

3)类文件是二进制格式,但它的文档很好。总体布局文档在wikipedia: http://en.wikipedia.org/wiki/Java_class_file#General_layout

特别有趣的是Constant池,它从类文件的第10字节开始,枚举从类文件中引用的所有常量。同样,它也被记录在维基百科上:http://en.wikipedia.org/wiki/Java_class_file#The_constant_pool。它的表项数以字节8和字节9(大端字节)存储。

常量池中特别有趣的是字符串和类引用。

字符串由第一个字节为1标识。接下来的两个字节是字符串的字节长度,其余字节(几乎)使用UTF-8。与UTF-8不同,更高的平面被存储为代理对(6字节而不是4字节),代码点0被非规范化存储。

类引用只是一个指向常量池的指针,指向类的完全限定名。完全限定名使用正斜杠而不是点来存储,以分隔完全限定名(java/lang/Object)。它被标记为7型。

常数池中的其他表项:类型3,4,9-12为4字节,类型7和8为2字节。类型5和6是8字节,但它们也占用常量池中的两个槽。

类文件的其余部分似乎并不介意常量池的字节长度是否改变。在常量池的末尾添加条目似乎也是安全的(一定要更新常量池的长度)。

4)由于jar文件只是一个zip文件,您所需要的就是用更新的内容重新打包原始文件。我不认为这是可能的,所以你可能需要一些文件变换。查看java.util.zip.ZipOutputStream的实现。

我可以反编译他们的插件,将它们加载到IDE中并手动更新它们,但我更喜欢有一个更全局的解决方案,你知道吗?此外,这是一个学习Java新技能的好机会。

我认为你应该学习的技能是:

  • 构建工具(例如Ant或Maven),允许您从源代码加载代码到IDE中进行重建,并且

  • 如何使用流编辑器(例如sed或awk)来更新源代码或宏预处理器(例如cpp或m4)来生成源代码

然而,考虑到Minecraft平台的性质,我不建议将其作为学习Java/Java技能的好地方。当然,破解/调整/修改字节码文件是大多数专业Java开发人员通常不需要或使用的技能。

最新更新