且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在字节码中确定哪里是super()方法调用,所有构造函数必须在JVM上执行

更新时间:2023-02-24 17:39:39

实际上,字节码构造函数的规则比Java的规则要宽松得多。

Actually, the rules for bytecode constructors are much more lax than Java's rules.

唯一的规则是必须在任何正常返回的路径上调用一个构造函数如果构造函数调用抛出异常,那么你也必须抛出异常。

The only rule is that exactly one constructor must be called on any path that returns normally and if a constructor call throws an exception, then you must throw an exception too.

除此之外,这意味着构造函数可能包含对其他构造函数的多次调用或者没有

Among other things, this means that a constructor may contain multiple calls to other constructors or none at all.

无论如何,确定给定调用特殊调用是否正在初始化当前对象的唯一保证方法是进行数据流分析,因为可以初始化同一类的其他对象,这会混淆一个天真的探测器。

Anyway, the only guaranteed way to determine whether a given invokespecial call is initializing the current object is to do a dataflow analysis, since it's possible to initialize other objects of the same class, which would confuse a naive detector.

编辑:这是一个完全有效的类(使用Krakatau汇编语法)的示例,显示了您可能遇到的一些问题。除此之外,它还调用了同一个类中的其他构造函数,构造函数的递归调用,以及在构造函数中构造同一个类的其他对象。

Here is an example of a perfectly valid class (using the Krakatau assembler syntax), showing some of the issues you could run into. Among other things, it has calls to other constructors in the same class, recursive invocation of constructors, and constructing other objects of the same class inside the constructor.

.class public ctors
.super java/lang/Object

; A normal constructor
.method public <init> : ()V
    .limit locals 1
    .limit stack 1

    aload_0
    invokespecial java/lang/Object <init> ()V
    return
.end method

; A weird constructor
.method public <init> : (I)V
    .limit locals 2
    .limit stack 5

    iload_1
    ifne LREST
        aload_0
        invokespecial ctors <init> ()V
        return

LREST:
    aload_0
    new ctors
    iinc 1 -1
    iload_1
LFAKE_START:
    invokespecial ctors <init> (I)V
LFAKE_END:
    iconst_0
    invokespecial ctors <init> (I)V
    return

.catch [0] from LFAKE_START to LFAKE_END using LCATCH
LCATCH:
    aload_0
    invokespecial java/lang/Object <init> ()V
    return
.end method

.method public static main : ([Ljava/lang/String;)V
    .limit locals 1
    .limit stack 2

    new ctors
    iconst_5
    invokespecial ctors <init> (I)V
    return
.end method