2011-07-11 6 views
17

メソッドはなぜvolatileになりますか?メソッドを揮発性にするとメソッドの動作がどのように変化しますか?Javaでメソッドをvolatileにするのはなぜですか?

編集:私はクラスオブジェクト(Java Reflection)によって返されたMethodオブジェクトに対してtoString()を行いました。戻り文字列には、publicの可視性とvoidの戻り値の型とともに、メソッド名に対する揮発性の修飾子がありました。研究により、揮発性の特性に関する情報のみが得られました。これが私がこの質問をした理由です。

メソッドの宣言されました:反射法について

public volatile org.osmdroid.api.IGeoPoint org.osmdroid.views.MapView.getMapCenter() 

コード:

public static class Test { 
    public static void showMethods(Object target) { 
     Class<?> clazz = target.getClass(); 
     for (Method method : clazz.getMethods()) { 
      if (method!=null) { 
       System.out.println(method.toString()); 
      } 
     } 
    } 
} 

メソッドの呼び出し:あなたがすることはできません

Test.showMethods(mapView); 
+11

方法は揮発性にすることはできません –

+0

私はこれがちょうどタイプミスであったと思っています... – mre

+0

このメソッドの宣言は何ですか? – EJP

答えて

38

私は強く、あなたが見ていることはJLSは、フィールドに対して次のビットが定義されているという事実の副作用があると思われる:

public static final int VOLATILE = 0x00000040; 

や方法については、以下ビット:

static final int BRIDGE = 0x00000040; 

これらは同じ値を持ちます(同じビットはメソッドとフィールドで異なる意味を持ちます)。

Modifier.toString(int)ドキュメントが示唆するように、なし:このようなコンストラクタまたは方法は、第1およびconstructorModifiersような方法から適切なマスクでtoStringの引数としてそのようなエンティティの既知の種類のチェックを実行する

注、またはmethodModifiers

あなたは不適切な出力を取得します(たとえば、共分散型の戻り値型の場合は自動生成され、「揮発性」として表示されます)。

少なくとも現在のOpenJDK Method.toString()はこれをフィルタリングします。あなたがそうでない場合は、これを正しく実行しない別のバージョンまたは古いバージョンのJDKを使用している可能性があります。

+0

私のjava -version出力: Javaのバージョン "1.6.0_20" OpenJDKのランタイム環境(IcedTea6 1.9.7)(6b20-1.9.7-0ubuntu1) OpenJDKの64ビットサーバーVM(19.0-B09を構築し、混合モード) 古すぎますか? – rsman

+0

追加されたコード私はクラスのメソッドを分析するために使用しました。 – rsman

+0

もう一つのヒントは、ブリッジメソッドは 'getDeclaredMethods()'、単に 'getMethods()'には現れないと思います。 – Cowan

15

volatileは、フィールドの有効な修飾語です。

+4

しかし、 'volatile 'ビットは' bridge method'ビットとして再利用されます(私の答えを見てください)。これは単純なバグだと思われます。 – Cowan

+0

@コーワン:はい、それは確かにそれのように聞こえる。 –

4

メソッドを揮発性にすることはできません。それはコンパイルされません。他のみんなが指摘されるよう

:あなたは方法は揮発性にすることはできません

9

はあなただけの答えを完全に行うために

http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html


を読みました。

+1

これはコメントでなければなりません。 – mre

+1

まあ、IMO、ここでのすべての答えはコメントでなければなりません。 –

+0

@Op De Cirkel、私はこの回答を例外として扱いました。 – mre

4

まず、Javaのvolatileメソッドはありません。完全停止。

Javaでは、フィールドをvolatileと宣言できます。 Java言語仕様では、目的を説明しています。

フィールドはvolatile宣言されている可能性があります。この場合、Javaメモリモデルはすべてのスレッドが変数に対して一貫した値を参照するようにします。

、我々は方法にそれを翻訳しようとした場合:揮発性の方法の場合には何かがすべてのスレッドがメソッドの一貫したバイトコードを参照することを、確実にするでしょう。しかし、それはとにかく保証されています。スレッドはクラスの異なるバージョンを表示しません。それらはすべてと同じ(コンパイルされた)バイトコードを参照してください(クラスローダーでトリックを演奏しない限り...)。

したがって、Javaのvolatileメソッドは必要ありません。

2

私はいくつかの研究を行いましたが、私の結論はコーワンと密接に似ています。次のコードは、JDKは、使用している何日JDK 1.6_13

public void go() 
{ 

    try 
    { 
     Class<?> forName = Class.forName("org.osmdroid.views.MapView"); 
     Method[] methods = forName.getMethods(); 
     for(Method m : methods) 
     { 
      String name = m.getName(); 
      if(name.equals("getMapCenter")) 
      { 
       System.out.println(m); 
      } 
     } 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

出力

public org.osmdroid.api.IGeoPoint org.osmdroid.views.MapView.getMapCenter() 
public org.osmdroid.util.GeoPoint org.osmdroid.views.MapView.getMapCenter() 

に正しい出力を生成し、それがどのバージョンですか?メソッドのtoString()を構築するために使用されるロジックは、熟読するのが面白いでしょう。

アンドロイド瓶に興味のある人は、ここで

http://code.google.com/p/osmdroid/downloads/list http://www.jarvana.com/jarvana/archive-details/com/google/android/android/1.5_r3/android-からダウンロードすることができます1.5_r3.jar

+0

Javaのバージョン: javaバージョン "1.6.0_20" OpenJDKランタイム環境(IcedTea6 1.9.7)(6b20-1.9.7-0ubuntu1) OpenJDK 64ビットサーバーVM(ビルド19.0-b09、混合モード) – rsman

+0

クラスのメソッドを分析するために使用したコードを追加しました。 – rsman

+1

は "1.6.0_20" OpenJDKのランタイム環境(IcedTea6 1.9.7)(6b20-1.9.7-0ubuntu1) OpenJDKの64ビットサーバーVM(ビルド Java版「Ubuntuの にOpenJDKの上で同じ出力を得ました19.0-b09、混合モード) ' –

0

ジェネリックメソッドの「グルーメソッド」として、Javaコンパイラによって「揮発性」メソッドが生成されているようです。ジェネリックスは、Objectのみをパラメータとして受け入れ、特定のジェネリック型にキャストするフードメソッドの下で生成しますが、これらのメソッドは開発者には見えません。 method.isBridge()

関連する問題