创建对象实例而不调用初始化程序 [英] creating object instance without invoking initializer
问题描述
我正在尝试生成字节码,这将创建没有代码初始化逻辑的对象实例。实际上,我想重现 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实现上都能使用。
- 致电sun。 misc.Unsafe.allocateInstance()内部API,可以在不调用构造函数的情况下实例化类。
- 在运行时生成类时,请从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.
- Call sun.misc.Unsafe.allocateInstance() internal API to instantiate a class without calling a constructor.
- 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屋!