2012-09-15 53 views
8

我想知道为什么在下面的字节码(用于抛出一个异常)的异常是重复的。Java字节码DUP

NEW java/lang/IllegalArgumentException 
DUP 
INVOKESPECIAL java/lang/IllegalArgumentException <init>()V 
ATHROW 
+0

我只需添加我的两分钱。 'NEW'只是在不调用任何构造函数的情况下分配对象memeory,'INVOKESPECIAL'将调用一个构造,但是这个调用将从栈中'this'指针中弹出,并且什么都不会推(构造函数返回void)。按照惯例,针对JVM的编译器将生成上面的'NEW/DUP/INVOKESPECIAL'序列来创建一个新对象。这是JVM认可的模式,可能会进行特殊优化... – csharpfolk

回答

10

我将线分析这条线,其中[] =新堆栈用于该运算后:

  1. NEW把一个新IllegalArgumentException到堆栈[SomeIllegalArgumentException]
  2. DUP重复它[SomeIllegalArgumentException,SomeIllegalArgumentException]
  3. INVOKESPECIAL弹出关闭顶部一个,并通过调用它的<初始化>方法初始化它[SomeIllegalArgumentException](init方法将不会返回到放回到堆叠中的对象,所以对象必须首先被复制,以便保持它在栈上)
  4. ATHROW抛出其他(重复关,我们初始化一个)[]
+7

如果你不那么认为它在栈上弹出并推入对象,而是谈论引用,这更容易理解。 – oldrinb

6

在字节代码中,首先由类创建的对象,然后一个构造函数被调用该对象上。对于void,构造函数的签名以V结尾,因为它返回任何内容。这意味着对象的原始引用的副本必须保存在堆栈中(或变量中),以便在构造函数被调用后抛出。

BTW对于一个构造的内部名称为<init>和用于静态初始化剂代码的内部名称是<clinit>

+1

这很合理,谢谢! – LanguagesNamedAfterCofee