创建对象实例而不调用初始化程序 [英] creating object instance without invoking initializer

查看:74
本文介绍了创建对象实例而不调用初始化程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  {
mv = cw.visitMethod(ACC_PUBLIC, newObjectInstance,()Ljava / lang / Object;,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;)调用错误的初始化方法



解决方案

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 /


    I'm trying to generate bytecode wich will create object instance without code initialization logic. Actually I want to reproduce generateSerializationConstructor behavior.

        {
            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();
        }
    

    unfortunally I got such error:

    java.lang.VerifyError: (class: com/esotericsoftware/reflectasm/benchmark/ConstructorAccessBenchmark$SomeClass_ClassAccess_, method: newObjectInstance signature: ()Ljava/lang/Object;) Call to wrong initialization method

    解决方案

    JVM specification prohibits creation of objects without calling proper constructor. However, there are two tricky ways of doing this. Both of them are specific to OpenJDK / Oracle JDK and are not guaranteed to work on all Java implementations.

    1. Call sun.misc.Unsafe.allocateInstance() internal API to instantiate a class without calling a constructor.
    2. When generating a class in run-time, inherit your class from sun.reflect.MagicAccessorImpl. JVM will skip bytecode verification for such class thus allowing to have NEW bytecode without proper INVOKESPECIAL.

    Both techniques are used in our custom serialization engine which can be found at https://github.com/odnoklassniki/one-nio/blob/master/src/one/nio/serial/

    这篇关于创建对象实例而不调用初始化程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆