【问题标题】:creating object instance without invoking initializer在不调用初始化程序的情况下创建对象实例
【发布时间】:2014-03-21 22:09:38
【问题描述】:

我正在尝试生成字节码,它将在没有代码初始化逻辑的情况下创建对象实例。其实我想重现generateSerializationConstructor的行为。

    {
        mv = cw.visitMethod(ACC_PUBLIC, "newObjectInstance", "()Ljava/lang/Object;", null, null);
        mv.visitCode();
        mv.visitTypeInsn(NEW, classNameInternal);
        mv.visitInsn(DUP);
        classNameInternal = "java/lang/Object";
        mv.visitMethodInsn(INVOKESPECIAL, classNameInternal, "<init>", "()V");
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }

不幸的是我得到了这样的错误:

java.lang.VerifyError: (class: com/esotericsoftware/reflectasm/benchmark/ConstructorAccessBenchmark$SomeClass__ClassAccess__, method: newObjectInstance signature: ()Ljava/lang/Object;) 调用错误的初始化方法

【问题讨论】:

    标签: java bytecode java-bytecode-asm


    【解决方案1】:

    JVM 规范禁止在不调用适当构造函数的情况下创建对象。 但是,有两种棘手的方法可以做到这一点。 它们都特定于 OpenJDK / Oracle JDK,并且不保证适用于所有 Java 实现。

    1. 调用 sun.misc.Unsafe.allocateInstance() 内部 API 来实例化一个类而不调用构造函数。
    2. 在运行时生成类时,从 sun.reflect.MagicAccessorImpl 继承您的类。 JVM 将跳过此类类的字节码验证,从而允许在没有适当 INVOKESPECIAL 的情况下使用新字节码。

    这两种技术都用于我们的自定义序列化引擎,可以在https://github.com/odnoklassniki/one-nio/blob/master/src/one/nio/serial/找到

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-15
      • 2022-12-07
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多