Java 为什么CgLib Beancopore中有一个无用的dup2(在我看来)

Java 为什么CgLib Beancopore中有一个无用的dup2(在我看来),java,jvm,java-bytecode-asm,cglib,jvm-bytecode,Java,Jvm,Java Bytecode Asm,Cglib,Jvm Bytecode,cglib的beancodier使用方法net.sf.cglib.beans.beancodier.Generator#generateClass根据您给出的类别获得特定的beancodier。但是在BeanCopier.java的第152行,有一个无用的dup2,我认为它在那里。我制作了我自己的BeanCopier,只是删除了第152行,它的其余部分与CGLIB BeanCopier.java相同,我的复印机仍在工作,没有任何异常或错误。 Cglib BeanCopier.java生成了字节码

cglib的beancodier使用方法net.sf.cglib.beans.beancodier.Generator#generateClass根据您给出的类别获得特定的beancodier。但是在BeanCopier.java的第152行,有一个无用的dup2,我认为它在那里。我制作了我自己的BeanCopier,只是删除了第152行,它的其余部分与CGLIB BeanCopier.java相同,我的复印机仍在工作,没有任何异常或错误。 Cglib BeanCopier.java生成了字节码

public void copy(java.lang.Object、java.lang.Object、net.sf.cglib.core.Converter);
代码:
0:aload_2
1:checkcast#13//课堂学习/复试/B
4:aload_1
5:checkcast#15//课堂学习/复印测试/A
8:2
9:invokevirtual#19//方法研究/copierTest/A.getA:()Ljava/lang/String;
12:invokevirtual#23//方法研究/copierTest/B.setA:(Ljava/lang/String;)V
15:返回
我的复印机没有dup2,还在工作

所以,我的问题是:dup2真的没用吗,或者我错过了dup2有用的一些情况


PS:我不熟悉java字节码,因此如果我问了一些愚蠢的问题,我很抱歉。

这只是一个有根据的猜测,但代码生成器很可能支持任意数量的属性,因此
dup2
确保两个bean引用保留在下一个属性的堆栈上


在这种情况下,代码生成器为每个属性生成
dup2
指令。最后一个属性可以省略它(这是本例中唯一的属性),但在处理属性描述符和生成代码时,需要对最后一个元素进行特殊处理,以便在生成的类文件中只保存一个字节。所以没有进行优化。

谢谢,我错过了这个任意数量的属性情况,我可能找到了为什么bean copier比纯get/set快得多的原因。它使用
dup2
确保两个bean引用保持在堆栈上,纯get/set将再次加载参数。我说得对吗?这取决于你所比较的替代方案是如何实施的。问题的代码接收两个
对象
并对每个对象执行类型转换,然后通过
dup2
重用结果,因此不需要重复类型转换。通过将结果存储到两个局部变量中,可以实现同样的效果,但这需要每个属性有两条
aload
指令,而不是一条
dup2
。不过,我并不期望堆栈和局部变量变量之间有显著的性能差异。但是重复类型转换的变体可能会更慢。即使JIT能够使用临时局部变量优化版本,使其与使用
dup2
的版本执行相同的操作,但使用
dup2
的版本在实践中可能会执行不同的操作,这仅仅是因为该方法更小,并且更渴望内联。它是否会更快取决于调用树的外观。虽然我发现较小的方法通常更可取,但不要对此进行过多解读;正如霍尔格所说,这种差异可能是难以察觉的。