有没有一种聪明的方法来确定Java字节码指令的长度?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了有没有一种聪明的方法来确定Java字节码指令的长度?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3665字,纯文字阅读大概需要6分钟。
内容图文
![有没有一种聪明的方法来确定Java字节码指令的长度?](/upload/InfoBanner/zyjiaocheng/703/31e313734fc241dfbcf541fb0bf35b5d.jpg)
我正在为Java创建一个静态分析工具,并且有一些关于我正在分析的程序的信息,如果我可以从.class文件中的字节码中获取它,将会更容易获得.
我不关心可能在类文件中的每一个instructions.例如,我可能只需要查看是否有任何getfield指令.
问题是,由于每条指令都有一个可变长度,似乎在一般情况下,我需要(在我的代码中)指定每个操作码的长度,然后才能确定(例如)getfield指令的开始和结束位置.
对于其他一些指令集(如x86),有一些规则,如“低于0x0F的任何操作码是1字节,任何等于或大于0x0F的操作都是两个字节.”
Java字节码指令中是否有这样的方便模式?
解决方法:
如果您尝试将指令操作码映射到指令大小,您将得到以下令人沮丧的表:
0 - 15 1 bytes
16 2 bytes
17 3 bytes
18 2 bytes
19 - 20 3 bytes
21 - 25 2 bytes
26 - 53 1 bytes
54 - 58 2 bytes
59 - 131 1 bytes
132 3 bytes
133 - 152 1 bytes
153 - 168 3 bytes
169 2 bytes
170 - 171 special handling
172 - 177 1 bytes
178 - 184 3 bytes
185 - 186 5 bytes
187 3 bytes
188 2 bytes
189 3 bytes
190 - 191 1 bytes
192 - 193 3 bytes
194 - 195 1 bytes
196 special handling
197 4 bytes
198 - 199 3 bytes
200 - 201 5 bytes
换句话说,没有在指令的数值和其位模式中编码的大小信息,但是还有另一个属性,您可以考虑某种模式:在~200个定义的指令中,大约150个指令的大小为一个字节,只留下约50条指令,完全需要处理.即便是这一小组指令也可以进一步细分为逻辑组,大多数占用三个字节,第二大组取两个字节.
所以冲过指令的方法代码可能如下所示:
static void readByteCode(ByteBuffer bb) {
while(bb.hasRemaining()) {
switch(bb.get()&0xff) {
case BIPUSH: // one byte embedded constant
case LDC: // one byte embedded constant pool index
// follow-up: one byte embedded local variable index
case ILOAD: case LLOAD: case FLOAD: case DLOAD: case ALOAD:
case ISTORE: case LSTORE: case FSTORE: case DSTORE: case ASTORE: case RET:
case NEWARRAY: // one byte embedded array type
bb.get();
break;
case IINC: // one byte local variable index, another one for the constant
case SIPUSH: // two bytes embedded constant
case LDC_W: case LDC2_W: // two bytes embedded constant pool index
// follow-up: two bytes embedded branch offset
case IFEQ: case IFNE: case IFLT: case IFGE: case IFGT: case IFLE:
case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPLT: case IF_ICMPGE:
case IF_ICMPGT: case IF_ICMPLE: case IF_ACMPEQ: case IF_ACMPNE:
case GOTO: case JSR: case IFNULL: case IFNONNULL:
// follow-up: two bytes embedded constant pool index to member or type
case GETSTATIC: case PUTSTATIC: case GETFIELD: case PUTFIELD:
case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case NEW:
case ANEWARRAY: case CHECKCAST: case INSTANCEOF:
bb.getShort();
break;
case MULTIANEWARRAY:// two bytes pool index, one byte dimension
bb.getShort();
bb.get();
break;
// follow-up: two bytes embedded constant pool index to member, two reserved
case INVOKEINTERFACE: case INVOKEDYNAMIC:
bb.getShort();
bb.getShort();
break;
case GOTO_W: case JSR_W:// four bytes embedded branch offset
bb.getInt();
break;
case LOOKUPSWITCH:
// special handling left as an exercise for the reader...
break;
case TABLESWITCH:
// special handling left as an exercise for the reader...
break;
case WIDE:
int widened=bb.get()&0xff;
bb.getShort(); // local variable index
if(widened==IINC) {
bb.getShort(); // constant offset value
}
break;
default: // one of the ~150 instructions taking one byte
}
}
}
我故意将一些指令分开,具有相同数量的后续字节,但具有不同的含义.毕竟,我想在某些地方插入一些实际逻辑.
注意,省略了对两个开关字节码指令的处理,它们需要填充,其实现需要知道缓冲区内的代码对齐,这是调用者的控制.这取决于您的具体应用.请参阅lookupswitch和tableswitch的文档.
当然,默认情况下处理所有单字节指令意味着代码不会捕获未知或无效的指令.如果你想要安全,你将不得不插入案件……
内容总结
以上是互联网集市为您收集整理的有没有一种聪明的方法来确定Java字节码指令的长度?全部内容,希望文章能够帮你解决有没有一种聪明的方法来确定Java字节码指令的长度?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。