你们有没有人知道一个工具会搜索.class文件然后显示他们的编译版本?
我知道你可以在十六进制编辑器中单独查看它们,但我有很多类文件要查看(我的巨型应用程序中的某些东西由于某种原因编译为Java6).
我想看看编译后的字节码,这样我就可以了解它在封面下的工作原理.我正在使用IntelliJ IDEA 15,但找不到查看字节码的方法.我错过了什么?
有一些框架用于动态字节码生成,操作和编织(BCEL,CGLIB,javassist,ASM,MPS).我想了解它们,但由于我没有太多时间知道所有这些细节,我希望看到一种比较图表,说明一种与其他的优缺点,以及对为什么.
在SO中,我发现了许多类似问题的问题,答案通常说"你可以使用cglib或ASM",或者"javassist比cglib更好",或者"BCEL已经老了,正在死"或"ASM是最好的,因为它给出X和Y".这些答案很有用,但并没有完全回答我想要的范围内的问题,更深入地比较它们并给出每个问题的优点和缺点.
bytecode-manipulation cglib javassist java-bytecode-asm jvm-bytecode
在 JVM 加载字节码期间,使用以下代码片段面对此 java.lang.VerifyError。
try{
-----
} catch (NumberFormatException|CalculationException e) {
}
Run Code Online (Sandbox Code Playgroud)
这里 CalculationException 是自定义异常,它扩展了 java.lang.RuntimeException,而 NumberFormatException 是标准的 Java RuntimeException。虽然代码在本地 Windows 机器上编译并运行良好。
它在 QA/prod/Dev unix 节点之一上因验证错误而失败,并在其他 unix 节点上正常工作。尽管两个 unix 节点具有相同的配置(使用 RedHat 6.2 和 1.8 jdk 以及相同版本的 jar 文件),但也比较了 javap -c 在两个节点上生成的字节码,发现相同。
我还找到了两种在错误节点上解决此问题的方法。
1)由于此错误是在字节码验证步骤中出现的,因此尝试通过将 dev unix 框上的字节码验证禁用为 -Xverify:none (也尝试过 -XX:-UseSplitVerifier 但 dint 工作,因为我认为它已从 jdk 8 中禁用)但是,由于我们不会在 prod 中禁用字节码验证,因此一直在寻找其他一些解决方法。
2) 另一种解决方法是使用父异常:catch 块中的 RuntimeException 而不是组合两个异常。
我无法理解 Java 是否确实对这种捕获方式有问题,为什么编译器 dint 抱怨它以及为什么它可以在一台机器上运行而不是在具有相同配置的其他机器上运行。错误原因也没有意义,它说:CalculationException (current frame, stack[0]) is notassignable to 'java/lang/RuntimeException 虽然它实际上是可分配的,经测试
if (RuntimeException.class.isAssignableFrom(CalculationException.class)){
System.out.println("Assisgnable");
}
Run Code Online (Sandbox Code Playgroud)
完整的异常详细信息: …
哪种解决方案更好?使用nullable lambda或传递空lambda作为默认参数?kotlin会以某种方式优化空的lambda吗?或者创建什么都不做的新实例?
class Test1(val action: () -> Unit = {})
不幸的是我不明白生成的字节码.让我们分析一下
val test11 = Test1()
反编译后给我们
private static final Test1 test11 = new Test1((Function0)null, 1, (DefaultConstructorMarker)null);
最后作为一个lambda传递这样的东西
var1 = (Function0)null.INSTANCE;
编辑:隐藏的问题是:Kotlin如何将空lambda视为默认值?
考虑简单的例子
private static String isPositive(int val) {
if (val > 0) {
return "yes";
} else {
return "no";
}
}
Run Code Online (Sandbox Code Playgroud)
这里非常简单:如果val > 0返回yes,则返回no.但是在编译之后,在字节码中,这个if条件被反转:
private static isPositive(I)Ljava/lang/String;
L0
LINENUMBER 12 L0
ILOAD 0
IFLE L1
L2
LINENUMBER 13 L2
LDC "yes"
ARETURN
L1
LINENUMBER 15 L1
FRAME SAME
LDC "no"
ARETURN
Run Code Online (Sandbox Code Playgroud)
它检查:如果val <= 0然后返回no,否则返回yes.
首先,我认为<=检查更便宜,而且它是某种优化.但是,如果我将我的初始代码更改为
if (val <= 0) {
return "no";
} else {
return …Run Code Online (Sandbox Code Playgroud) 我正在使用IntellijIDEA Ultimate Edition.浏览.class从java源代码编译的文件很简单:我只需双击.class文件即可,IDEA会对其进行反编译.
但是,对于.class从scala源代码编译的文件,它不起作用.似乎IDEA只是引用了scala源文件.
我注意到IDEA的行为只有scala plugin安装后才有.没有它,它工作正常.有没有办法在不关闭的情况下使用IDEA进行反编译scala plugin?
JVM规范的某些部分建议操作JSR(Jump SubRoutine),JSR_W(Jump SubRoutine Wide)和RET(从子例程返回)仅可用于类文件版本50.0(JDK 1.6):
(本节假设编译器生成版本号为50.0或更低版本的类文件,以便可以使用jsr指令.另请参见§4.10.2.5.)
然后:
要实现
try-finallyconstruct,生成class版本号为50.0或更低版本的文件的Java编程语言的编译器可以使用异常处理工具和两个特殊指令:jsr("跳转到子例程")和ret("从子例程返回" ").
另一方面,操作码描述本身并未说明这些功能的弃用.引用的文本只说明过去50.0版本中的版本如何,但在此之后并没有明确说明事态.
这个评论(对于询问这种弃用或删除背后的动机的问题)表明了类似的混淆程度,所以显然我并不是唯一一个寻找此问题的人.
我刚刚看到 EBean 以一种让我感觉奇怪的方式对记录类文件进行字节码转换,我寻求从 JVM 角度来看这是否合法的答案。
显然,可以有一个类文件,其中类扩展java.lang.Record并定义记录组件属性(因此它是一个“记录”,就像 javac 会创建它一样),但具有 javac 不允许的以下附加“功能”:
对我来说,这似乎是非法的,我预计会出现 JVM 验证错误。我想知道这是否是“受支持”的东西,我可以在此基础上进行构建,或者缺乏验证是否是 JVM 错误。难道记录只是Java语言的一个特性,没有JVM的支持吗?!我读到记录的最终字段是“真正的最终”,即使通过反射也无法更改,并且假设必须有特殊的 JVM 支持来确保记录与 Java 语言语义相匹配......
我有两个示例类文件,一个来自示例Java应用程序,另一个来自示例C app(使用LLJVM编译为字节码).
看看他们的输出,我可以通过javap -c -p看到,为了初始化(静态)字段,Java应用程序显示以下块:
static {};
Code:
0: sipush 1339
3: putstatic #7 //Field SRV_ID
etc
Run Code Online (Sandbox Code Playgroud)
<clinit>如果我理解的话,基本上就是这个方法.或者由我正在使用的VM检测到.
然而,C-app有这个:
public {};
Code:
0: sipush 1339
3: putstatic #7 //Field SRV_ID
etc
Run Code Online (Sandbox Code Playgroud)
这是什么?我的VM没有检测到它.
示例类文件.第一个来自Java应用程序打印消息并等待20秒,重复.第二个是大致相同的C应用程序.
http://www.fast-files.com/getfile.aspx?file=156962
http://www.fast-files.com/getfile.aspx?file=156961
这样做的道歉 - 我不会立即知道如何附加文件或有效地显示.class文件.
jvm-bytecode ×10
java ×6
jvm ×4
bytecode ×3
kotlin ×2
cglib ×1
decompiling ×1
finally ×1
java-record ×1
javassist ×1
lambda ×1
opcode ×1
scala ×1