创建对象实例而不调用初始化程序

时间:2014-03-21 22:09:39

标签: java bytecode java-bytecode-asm

我正在尝试生成字节码,它将创建没有代码初始化逻辑的对象实例。实际上我想重现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 _,方法:newObjectInstance签名:()Ljava / lang / Object;)调用错误初始化方法

1 个答案:

答案 0 :(得分:8)

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

  1. 调用sun.misc.Unsafe.allocateInstance()内部API来实例化一个类而不调用构造函数。
  2. 在运行时生成类时,从sun.reflect.MagicAccessorImpl继承您的类。 JVM将跳过此类的字节码验证,从而允许在没有正确的INVOKESPECIAL的情况下使用新的字节码。
  3. 我们的自定义序列化引擎中使用了这两种技术,可以在https://github.com/odnoklassniki/one-nio/blob/master/src/one/nio/serial/

    找到