理解Java字节码

19

经常情况下,我所面对的是没有源代码的Java类文件,我需要理解手头遇到的问题。

请注意,反编译器虽然有用,但并不是所有情况下都足够...

我有两个问题

  1. 有哪些工具可以查看Java字节码(最好能够从Linux命令行使用)?
  2. 有哪些好的参考资料可以熟悉Java字节码语法?
6个回答

19

与其直接查看Java字节码,需要熟悉Java虚拟机及其操作,可以尝试使用Java反编译工具。反编译器将尝试从指定的class文件中创建一个java源文件。

如何“反编译”Java类文件?是一个相关的问题,它可以帮助了解如何反编译Java class文件。

话虽如此,可以使用JDK中的javap命令来反汇编Java类文件。 javap的输出是包含在类文件中的Java字节码。但请注意,字节码与Java源代码完全不同。

学习Java字节码和Java虚拟机本身的明确来源将是Java虚拟机规范第二版。特别是,第6章:Java虚拟机指令集具有所有字节码指令的索引。


请查看我的反编译器评论。 - hhafez
@hhafez:我猜你的问题“理解Java字节码”已经得到了回答,是吗? - Ryan Fernandes

17

要查看Java类文件的字节码指令,请使用javap -v命令,与运行Java程序的方式相同,指定类路径(如果需要)和类名。

例如:

javap -v com.company.package.MainClass

关于字节码指令集,指令集摘要


1
这个答案完全涵盖了原问题的两个方面。 - CyberMJ

2
Fernflower是一款分析反编译器,它可以将类反编译为可读的Java代码而非字节码。当你想要理解代码如何工作时,它非常有用。请点击此处查看Fernflower

1

如果你有一个类但没有源代码,但是你发现了一个 bug,你可以做以下两件事情:

  1. 反编译,修复 bug 并重新创建 jar 文件。我以前做过这个,但系统管理员对将其投入生产持谨慎态度。
  2. 为该类编写单元测试,确定导致 bug 的原因,使用单元测试报告 bug 并等待修复。

    (2) 通常是我经验中系统管理员更喜欢的方法。

    如果你选择 (2),那么在此期间,由于你知道 bug 的原因,你可以防止输入进入该类,以避免问题,或者在错误发生时准备妥善处理它。

    你还可以使用 AspectJ 将代码注入到问题类中,并更改方法的行为而无需重新编译。我认为这可能是更可取的选项,因为你可以为可能调用该函数的所有代码更改它,而不必担心教会每个人如何解决问题。

    如果你学会了阅读字节码指令,你会怎么解决这个问题呢?


  1. 我不知道你可以使用AspectJ在.class中插入代码,我以为它只能在Java上工作,但我想我错了。
  2. 当我找出问题时,我该怎么办?很多时候,找出问题的真正原因已经是解决问题的一半了。
- hhafez
@hhafez - 你可以在运行时将方面织入类中,但是这样做可能会违反许可证,所以要小心一点。单元测试可能是最好的选择,但如果代码不可测试,则反编译成为一种选择,但这是一个缓慢的过程,在我看来。 - James Black

0
我有两个问题: 1)有哪些可以查看Java字节码的工具(最好是从Linux命令行中可用)? javap工具(使用-c选项)可以反汇编字节码文件。它在命令行上运行,并作为Java SDK的一部分提供。 2)了解Java字节码语法的好参考资料有哪些? javap工具使用与JVM规范相同的语法,而JVM规范自然是权威的来源。我还注意到Bill Venners的《Inside the Java Virtual Machine》。虽然我从未读过,但它看起来可能已经绝版了。 实际(文本)语法很简单且不言自明... 假设你有一个解释字节码操作的参考资料,并且对阅读这个层次的代码有一定的了解,那么它应该比较容易理解。但是,即使字节码经过混淆器处理,通过反编译器阅读输出也会更加容易。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接