方法签名中的'volatile'是什么意思?

6

这个有点奇怪。我有以下代码:

class A
{   
    protected A clone() throws CloneNotSupportedException
    {
        return (A) super.clone();       
    }
}

当我通过'showmycode.com'反编译它的字节码时,它显示了以下代码:
class A
{

    A()
    {
    }

    protected A clone()
    throws clonenotsupportedexception
    {
        return (A)super.clone();
    }

    protected volatile object clone()
    throws clonenotsupportedexception
    {
        return clone();
    }
}

第二个“克隆”方法中,方法的返回类型为volatile是什么意思?(此代码是通过Eclipse默认的JDK 1.6编译器编译的)。


5
我认为这个答案适用于这里:https://dev59.com/62w15IYBdhLWcg3wYaox - Kai Sternad
@bunting 谢谢。您能在您的回答中提及它吗?这样我才能接受它。 - shrini1000
4个回答

8

这个问题已经在 为什么要在Java中使方法变成volatile? 中得到了回答。但是这里还有一些更多的信息。

当你重载方法时(可能只有在超类中的泛型方法),该方法被标记为是一个“桥方法”。来自 java.lang.reflect.Modifier

static final int BRIDGE    = 0x00000040;

不幸的是,这也是用于标记字段为volatile的位:

public static final int VOLATILE         = 0x00000040;

如果你在该方法上打印修饰符,你会看到类似下面的内容:
public volatile

Modifiers.toString(int) 方法中的一个限制是无法确定它是字段还是方法。

public static String toString(int mod) {
    StringBuffer sb = new StringBuffer();
    ...
    if ((mod & VOLATILE) != 0)  sb.append("volatile ");
    // no mention of BRIDGE here
    ...
    return sb.toString().substring(0, len-1);
}

4
字段和方法的修饰符掩码相似但并不完全相同。反编译器最可能在此处使用toString方法。http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/reflect/Modifier.java。然而它没有处理所有的位。
// Bits not (yet) exposed in the public API either because they
// have different meanings for fields and methods and there is no
// way to distinguish between the two in this class, or because
// they are not Java programming language keywords

它不能处理的是那些可能意味着合成桥接的位,这些位标识编译器生成的代码。

如果volatile在这里有任何意义,它可能意味着即使它什么也不做,也不要删除该方法。


这不是一个 bug。似乎为泛型所需的生成方法会在编译后的类中被静默插入,并被标记为“volatile”,即使这不是它们确切的含义。 - Panayotis

4

这并没有什么实际意义,只是反编译器中的一个 bug,就此结束。

(这个 bug 可能与类文件格式中使用的某些标志位“重载”有关,在类、字段或方法的上下文中含义不同。我也模糊地记得在最近的 JVM 规范修订版中出现了一些“新用途”。)


1

你的反编译器有一个 bug。

volatile 只是字段的有效修饰符。

我建议你阅读 this 文章。


1
我明白了。我的问题是:为什么反编译的代码在方法签名中有“volatile”,而原始代码没有呢?似乎只有桥接方法才会出现这种情况。 - shrini1000
@shrini1000,尝试编译您反编译的代码-您会发现它无法编译。在Java中,您不能使用volatile修饰符标记方法。我猜这是您用于反编译的工具的错误。 - aviad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接