[高难度]Java的class文件中的常量池概述 - 编程开发 - Minecraft(我的世界)中文论坛 -.htm

[高难度]Java的class文件中的常量池概述 - 编程开发 - Minecraft(我的世界)中文论坛 -

Minecraft(我的世界)中文论坛

 找回密码
 注册(register)

!header_login!

只需一步,立刻登录

查看: 8685|回复: 11
打印 上一主题 下一主题

[其它开发教程] [高难度]Java的class文件中的常量池概述

[复制链接]
linnaea 当前离线
积分
875
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-6-11
查看详细资料

来自:上海

跳转到指定楼层
楼主
发表于 2014-6-14 15:22:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x
本帖最后由 linnaea 于 2014-6-14 15:24 编辑

首先请确保你会Java,不然我可以保证你看的一头雾水

对于汉化那些消息都写在class文件里的插件,这些东西还是比较有用的还有这些东西比较难懂,所以尽管问……

首先每个class文件中都有一个常量池,其中会存放不少东西,包括字符串
常量池中的数据分成14种,以下是比较常见的11种和他们之间的引用关系
  1. Fieldref_info           --\     /--> Class_info       --\
  2. Methodref_info          ---+===+---> NameAndType_info ---+===> Utf8_info
  3. InterfaceMethodref_info --/                             /
  4. String_info--------------------------------------------/

  5. Integer_info
  6. Float_info
  7. Long_info
  8. Double_info
复制代码
Fieldref_info:表示类中的字段
Methodref_info:表示中的方法
InterfaceMethodref_info:表示接口中的方法
Class_info:表示类和接口
NameAndType_info:表示字段或方法的名称和类型,含有两个对Utf8_info的引用
String_info:表示字符串常量
Utf8_info:实际保存字符串的地方
Integer_info:保存一个32位整数
Float_info:保存一个32位单精度浮点数
Long_info:保存一个64位整数,在这个常量后的一个常量必须是有效的,但是会被忽略(也就是不能使用)
Double_info:保存一个64位双精度浮点数,同上

常量池中的常量从1开始编号,最大为65535
class文件中,所有的数据都是大尾序的(也就是说,0x01020304保存为0x01 0x02 0x03 0x04四个字节,而小尾序是0x04 0x03 0x02 0x01)


对类的引用在class文件中表示为一个Class_info,这个结构中有一个表示相应的Utf8_info的编号的字段,而相应的Utf8_info中会记录实际的类名
类的名字很容易看,比如Java中的类com.example.foo.Bar,记录在class文件中时,把.换成/即可,也就是com/example/foo/Bar

对字段的引用在class文件中表示为一个Fieldref_info,这个结构中有一个表示所属的类的Class_info的编号的字段,还有一个表示字段名称和类型的NameAndType_info
NameAndType_info中有两个Utf8_info的编号,一个是名字,另外一个是类型。
class文件中,类型的信息是有自己的一个表示方式的。byte记为B,char记为C,double记为D,float记为F,int记为I,long记为J,short记为S,boolean记为Z,而某个特定的类记为 L类名; ,数组则是在相应的类型前加上[
比如,byte[]是[B,String[][]是[[Ljava/lang/String;,com.example.foo.Bar类型记为Lcom/example/foo/Bar;


对方法的引用和对字段的引用大体上是一样的,区别在于类型的标记方式。
一个方法可以接受多个参数,并且可以返回一个值(或者void类型,没有返回值)
这些信息一样是记录在NameAndType_info中表示类型的那个Utf8_info里的,记录方法是
  1. (参数1类型 参数2类型 ...)返回类型
复制代码
(注意实际上是没有空格的,这里的空格只是方便阅读)
特别的,对于void的返回类型,记作V
举例:java.lang.StringBuilder.append
  1. Methodref_info ---+---> Class_info        -------> Utf8_info "java/lang/StringBuilder"
  2.                    \--> NameAndType_info  ---+---> Utf8_info "append"
  3.                                               \--> Utf8_info "(Ljava/lang/String;)Ljava/lang/StringBuilder;"
复制代码
java.lang.Object.toString
  1. Methodref_info ---+---> Class_info        -------> Utf8_info "java/lang/Object"
  2.                    \--> NameAndType_info  ---+---> Utf8_info "toString"
  3.                                               \--> Utf8_info "()Ljava/lang/String;"
复制代码
boolean foobar(int i, double d, Thread t) (只表示NameAndType_info部分)
  1. NameAndType_info  ---+---> Utf8_info "foobar"
  2.                       \--> Utf8_info "(IDLjava/lang/Thread;)Z"
复制代码

对于字符串常量,String_info里有一个记录对应Utf8_info的编号的字段。非常简单的东西。


然后我们来考虑插件汉化……
考虑这种情况:你的程序里有一个地方使用了java.lang.StringBuilder.append(字符串之间用+都会用到这个),然后你又有一个字符串常量是"append"
那么在class文件里看起来就是这样的:
  1. Methodref_info ---+---> Class_info        --------> Utf8_info "java/lang/StringBuilder"
  2.                    \--> NameAndType_info  ---+----> Utf8_info "(Ljava/lang/String;)Ljava/lang/StringBuilder;"
  3.                                               \
  4. String_info    --------------------------------+--> Utf8_info "append"
复制代码
然后你把append汉化成“附加”了,于是本来调用java.lang.StringBuilder.append的地方就都变成java.lang.StringBuilder.附加,GG……(我没用过hhclass,不过我猜可能是这个原因导致有些插件没法汉化)
正确的做法:单独添加一个Utf8_info常量,内容是“附加”,然后把本来指向“append”的String_info改为指向这个新的常量。
软件的话,http://classeditor.sourceforge.net/

来练个手吧w
这是某个class文件中的常量池的一部分:
#8 Fieldref_info    Class_info#137,NameAndType_info#253
#39 String_info  Utf8_info#149
#63  Methodref_Info   Class_info#137,NameAndType_info#314
#137 Class_info   Utf8_info#375
#149 Utf8_Info  "compressor"
#150 Utf8_Info  "Lnet/jpountz/lz4/LZ4Compressor;"
#204 Utf8_Info  "setWorldsAutoSaving"
#205 Utf8_Info  "(Z)V"
#253 NameAndType_Info   Utf8_info#149  Utf8_info#150
#314 NameAndType_Info   Utf8_info#204  Utf8_info#205
#375 Utf8_Info "name/linnaea/mbdelta/cb/BukkitPlugin"
请试着指出Methodref_Info#63表示的方法所在的类,及其原型

请试着指出Fieldref_info#8表示的字段所在的类,以及字段的名称和类型

请试着指出String_info#39表示的字符串



之后我可能会试着自己写个这种东西,方便汉化什么的
不过这些东西放这里的话,我觉得肯定会有人比我先完成,因为……












我懒啊

评分

参与人数 7人气 +9金粒 +87收起 理由
MOLGYPETER+ 1学完jvm就感觉很亲切
common+ 2+ 40ByteCode大法好
gooding300+ 2+ 10Bytecode大法好w望继续深入
andylizi+ 2欢迎来到bytecode编程
liuhui1362+ 1+ 20Mcbbs有你更精彩~
taoo7+ 1+ 5Mcbbs有你更精彩~
q513902026+ 12教程不错

查看全部评分

帖子永久链接: 

Minecraft中文论坛 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖若有内容转载自其它媒体,不代表本站赞同其观点和对其真实性负责
6、若本帖涉及任何版权问题,请立即告知本站,本站将及时予以删除并致以最深的歉意
7、Minecraft(我的世界)中文论坛管理员和版主有权不事先通知发贴者而删除本文

250=mo 当前离线
积分
9702
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2012-10-21
查看详细资料

来自:广东

沙发
发表于 2014-6-14 15:25:18 | 只看该作者
你成功保障了我看得一头雾水,哈哈
回复

使用道具 举报

叫我stere 当前离线
积分
4126
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-4-5
查看详细资料

来自:安徽

板凳
发表于 2014-6-14 15:28:10 | 只看该作者
同上.......
回复

使用道具 举报

Notme. 当前离线
积分
709
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-4-14
查看详细资料

来自:福建

地板
发表于 2014-6-14 15:30:02 | 只看该作者
= = 好深奥。。
回复

使用道具 举报

yangzhen0021 当前离线
积分
754
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2013-10-12
查看详细资料

来自:浙江

5#
发表于 2014-6-14 15:53:59 | 只看该作者
楼主加油!~哇啦啦~
回复

使用道具 举报

youliao 当前离线
积分
6069
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2013-8-6
查看详细资料

来自:浙江

6#
发表于 2014-6-14 15:54:15 | 只看该作者
哦,原来汉化是这样的,长知识了。
回复

使用道具 举报

梦幻龙族Ⅱ 当前离线
积分
1730
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2013-2-18
查看详细资料

来自:天津

7#
发表于 2014-6-16 06:59:19 | 只看该作者
原来字节码是这样的,长见识了。
回复

使用道具 举报

linnaea 当前离线
积分
875
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-6-11
查看详细资料

来自:上海

8#
 楼主| 发表于 2014-6-16 10:45:18 | 只看该作者
梦幻龙族Ⅱ 发表于 2014-6-16 06:59
原来字节码是这样的,长见识了。

字节码和执行栈之类的我还没讲到呢……
回复

使用道具 举报

梦幻龙族Ⅱ 当前离线
积分
1730
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2013-2-18
查看详细资料

来自:天津

9#
发表于 2014-6-16 11:12:10 | 只看该作者
哦,好吧。常量池原来是这样的~
回复

使用道具 举报

Ph-苯 当前离线
积分
12442
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-3-24
查看详细资料

来自:江西

10#
发表于 2019-8-4 12:02:00 来自手机 | 只看该作者
请问
--\ --/
\--> /-->
---+===+--->
---+===>
---+--->
------->
分别是什么意思?
我从未见过,完全看不懂这些符号。
回复

使用道具 举报

UltraPanda 当前离线
积分
3581
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-5-28
查看详细资料

来自:山东

11#
发表于 2019-8-6 11:12:00 | 只看该作者
使用 Anthony大佬 的 Koffee反汇编 会简单一些。
回复

使用道具 举报

lovexyn0827 当前离线
积分
1346
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-2-1
查看详细资料

来自:山东

12#
发表于 2021-2-7 01:40:55 | 只看该作者
学过汇编,用过Mixin的表示轻松
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册(register)

本版积分规则

Archiver|小黑屋|Mcbbs.net ( 京ICP备15023768号-1 ) | 京公网安备 11010502037624号 | 手机版

GMT+8, 2023-4-18 16:05 , Processed in 0.050334 second(s), Total 25, Slave 24 queries, Release: Build.2023.03.15 0137, Gzip On, Redis On.

"Minecraft"以及"我的世界"为美国微软公司的商标 本站与微软公司没有从属关系

© 2010-2022 我的世界中文论坛 版权所有 本站内原创内容版权属于其原创作者,除作者或版规特别声明外未经许可不得转载