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

时间:2012-12-30 19:51:28

标签: java class minecraft bytecode-manipulation import

有什么问题? 我是一个Minecraft服务器管理员/服务器主机/插件开发人员,但发现在核心游戏的每个新版本上更新我自己的个人插件是一个绝对的烦恼。它并不总是这样,我已经有20个版本的插件工作,而不会破坏过去。考虑到我过去从未做过这样的事情,每个月必须坐下来更新40个插件,这是我生活中不必要的烦恼。

导致此问题的原因是什么? 在每个新版本中,它们都要求您在已编译的jar文件中使用不同的导入,从而强行破坏任何过时(但可能仍在工作)的jar文件。相信我。我可以阅读错误日志,知道何时需要实际出去下载新的更新。我现在不需要保护自己。这只是一场比赛,我没有多少骑在上面。

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

  1. 获取X_Folder
  2. 中所有jar文件的列表
  3. 为每个jar文件,让所有类都被包围。
  4. 对于每个类文件,搜索Y_STRING的任何实例并将其替换为Z_STRING。
  5. 确保所有内容都正确地放回到jar文件中。
  6. 进行。
  7. 问题吗 我如何编写类文件编辑方法?我甚至不知道如何开始。

    声明 对不起听起来好像我还没有开始研究这个。我只是,没有任何字节码操作经验。我已经看过几个例子,但还没有看到有关重命名导入的事情。希望有人在这里可以帮助我。谢谢!

2 个答案:

答案 0 :(得分:2)

  
      
  1. 获取X_Folder
  2. 中所有jar文件的列表   
  3. 为每个jar文件,让所有类都被包围。
  4.   
  5. 对于每个类文件,搜索Y_STRING的任何实例并将其替换为Z_STRING。
  6.   
  7. 确保所有内容都正确地放回到jar文件中。
  8.   
  9. 进行。
  10.   

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

2)JAR文件是具有特定内容的ZIP文件。查看java.util.jar.JarFilejava.util.zip.ZipInputStream;迭代其条目(JarFile#entries())并解压缩(JarFile#getInputStream(ZipEntry))内的每个类文件。

3)类文件是二进制格式,但记录得很好。维基百科上记录了总体布局:http://en.wikipedia.org/wiki/Java_class_file#General_layout

特别感兴趣的是常量池,它从类文件的第10个字节开始,并枚举从类文件中引用的所有常量。它再次记录在维基百科上:http://en.wikipedia.org/wiki/Java_class_file#The_constant_pool。其条目数存储在字节8和9(big-endian)中。

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

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

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

常量池中的其他条目:类型3,4,9-12是四字节,类型7和8是双字节。类型5和6是八字节,但它们也占用常量池中的两个插槽。

如果常量池的字节长度发生变化,那么类文件的其余部分似乎并不介意。在常量池末尾添加条目似乎也是安全的(确保更新常量池长度)。

4)由于jar文件只是一个zip文件,所以您只需要使用更新的内容重新打包原始文件。我不希望这可能是就地的,所以你可能需要一些文件改组。查看java.util.zip.ZipOutputStream的实施情况。

答案 1 :(得分:0)

  

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

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

  • 构建工具(例如Ant或Maven),允许您从源代码重建源代码到IDE,

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

然而,鉴于Minecraft平台的性质,我不建议将它作为学习Java / Java技能的好地方。当然,黑客/调整/按摩字节码文件是大多数专业Java开发人员通常不需要或不会使用的技能。