java - 是否可以在现有实例上调用构造函数?

标签 java reflection jvm unsafe

众所周知,使用sun.misc.Unsafe#allocateInstance可以创建一个对象,而无需调用任何类构造函数。

是否可以做相反的事情:给定一个现有实例,调用它的构造函数?

<小时/>

澄清:这不是关于我在生产代码中执行的操作的问题。我对 JVM 内部结构和仍然可以完成的疯狂事情感到好奇。欢迎特定于某些 JVM 版本的答案。

最佳答案

JVMS §2.9禁止在已初始化的对象上调用构造函数:

Instance initialization methods may be invoked only within the Java Virtual Machine by the invokespecial instruction, and they may be invoked only on uninitialized class instances.

但是,在使用 JNI 初始化对象上调用构造函数仍然是技术上可行的CallVoidMethod函数 <init> 之间没有区别和普通的 Java 方法。此外,JNI 规范暗示 CallVoidMethod 可以用于调用构造函数,尽管它没有说明是否必须初始化实例:

When these functions are used to call private methods and constructors, the method ID must be derived from the real class of obj, not from one of its superclasses.

我已经验证以下代码可以在 JDK 8 和 JDK 9 中运行。JNI 允许您执行不安全的操作,但您不应在生产应用程序中依赖这一点。

ConstructorInvoker.java

public class ConstructorInvoker {

    static {
        System.loadLibrary("constructorInvoker");
    }

    public static native void invoke(Object instance);
}

constructorInvoker.c

#include <jni.h>

JNIEXPORT void JNICALL
Java_ConstructorInvoker_invoke(JNIEnv* env, jclass self, jobject instance) {
    jclass cls = (*env)->GetObjectClass(env, instance);
    jmethodID constructor = (*env)->GetMethodID(env, cls, "<init>", "()V");
    (*env)->CallVoidMethod(env, instance, constructor);
}

TestObject.java

public class TestObject {
    int x;

    public TestObject() {
        System.out.println("Constructor called");
        x++;
    }

    public static void main(String[] args) {
        TestObject obj = new TestObject();
        System.out.println("x = " + obj.x);  // x = 1

        ConstructorInvoker.invoke(obj);
        System.out.println("x = " + obj.x);  // x = 2
    }
}

关于java - 是否可以在现有实例上调用构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48616630/

相关文章:

java - 检测 java.io.FileNotFoundException 的根本原因

C# 创建类的实例并在字符串中按名称设置属性

java - JRuby 中的安全级别

java - 简单算术代码

java - fitCenter 算法 ImageView

java - Android 使用带有空格的键访问 Firebase

c - 非动态加载代码的类似 dlsym 的功能?

c# - 使用 Activator 创建实例

java - Java 中的初始 ArrayList 大小取决于内存?

java - 这个演示中的 JVM 内存分配和释放解释?