2011-07-11 12 views
17

¿Por qué se volvía volátil un método? ¿Cómo cambia un método volátil el comportamiento del método?¿Por qué hacer un método volátil en Java?

Editar: Hice un toString() en un objeto de método devuelto por un objeto de clase (reflexión de Java). La cadena de retorno tenía un modificador volátil contra el nombre del método junto con la visibilidad pública y el tipo de devolución nula. La investigación arrojó solo información sobre las propiedades volátiles. Es por eso que hice esta pregunta.

La declaración de método era:

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

para el método de reflexión:

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()); 
      } 
     } 
    } 
} 

Método de invocación:

Test.showMethods(mapView); 
+11

El método no puede ser volátil –

+0

Espero que esto haya sido un error ... – mre

+0

¿Cuál es la declaración del método? – EJP

Respuesta

38

tengo la fuerte sospecha de que lo que se está viendo es un efecto secundario del hecho de que el JLS se definen los siguientes campos de bits para:

public static final int VOLATILE = 0x00000040; 

y el siguiente bit para métodos:

static final int BRIDGE = 0x00000040; 

Tenga en cuenta que tienen el mismo valor (el mismo bit tiene un significado diferente para los métodos y campos).

Si llamas, p. Modifier.toString(int) sin que, como la documentación sugiere:

Tenga en cuenta que para realizar tal comprobación de un tipo conocido de la entidad, como un constructor o método, en primer lugar y el argumento de toString con la máscara apropiada en un método como constructorModifiers o methodModifiers.

y obtendrá resultados inadecuados (incluidos los métodos de puente, autogenerados para, por ejemplo, el tipo de retorno covariante, que aparecen como 'volátiles').

Al menos el actual OpenJDK Method.toString() lo filtra; si el tuyo no lo es, quizás estés usando una versión diferente o anterior del JDK que no hace esto correctamente.

+0

Mi salida de java -version: versión java "1.6.0_20" OpenJDK Runtime Environment (icedtea6 1.9.7) (6b20-1.9.7-0ubuntu1) OpenJDK 64 bits VM Server (build 19.0-b09, modo mixto) ¿Demasiado viejo? – rsman

+0

Código agregado que utilicé para analizar los métodos de la clase. – rsman

+0

Otra sugerencia sería que (creo) los métodos de puente no aparecerán en 'getDeclaredMethods()', solo 'getMethods()'. – Cowan

15

No se puede. volatile es solo un modificador válido para un campo.

+4

Pero el bit 'volátil' se reutiliza como el método' bridge' (ver mi respuesta), así que sospecho que se trata de un error simple. – Cowan

+0

@Cowan: Sí, ciertamente suena así. –

4

No puede hacer que un método sea volátil. No compilará

9

¿Ha leído

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


sólo para la completa respuesta:

como todo el mundo está señalando: no se puede hacer un método volátil.

+1

Esto debería ser un comentario. – mre

+1

Bueno, IMO, todas las respuestas aquí deberían ser comentarios, así que sería solo un –

+0

@Op De Cirkel, hice de esta respuesta una excepción porque solo se proporcionó un enlace, que es lo que normalmente se hace en los comentarios. – mre

4

En primer lugar, no volatile métodos en Java. Punto final.

Java permite declarar los campos como volatile. La especificación del lenguaje Java explica el propósito:

Un campo puede declararse volátil, en cuyo caso el modelo de memoria Java garantiza que todos los subprocesos vean un valor constante para la variable.

Ahora, si tratamos de traducir a métodos: en caso de un método volátil algo aseguraría que todos los hilos de ver un código de bytes coherente para el método. Pero eso está garantizado de todos modos. Los hilos no ven diferentes versiones de una clase, todos ellos ver el mismo código de bytes (compilado) (siempre que no jueguen trucos con los cargadores de clases ...).

Así que no hay necesidad de métodos volatile en Java.

2

Hice algunas investigaciones y mis conclusiones reflejan de cerca a Cowan. El siguiente código produce la salida correcta en un JDK de Sun 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(); 
    } 
} 

salida

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

Lo JDK está usando y qué versión es? La lógica utilizada para construir el Método toString() sería interesante de leer detenidamente.

Las personas interesadas en el tarro de Android pueden descargar desde aquí

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

La versión de Java: java version "1.6.0_20" OpenJDK Runtime Environment (icedtea6 1.9.7) (6b20-1.9.7-0ubuntu1) OpenJDK 64 bits VM Server (build 19.0-b09, modo mixto) – rsman

+0

Código agregado que utilicé para analizar los métodos de la clase. – rsman

+1

consiguió el mismo resultado en el OpenJDK en Ubuntu 'versión java "1.6.0_20" OpenJDK Runtime Environment (icedtea6 1.9.7) (6b20-1.9.7-0ubuntu1) OpenJDK 64 bits del servidor VM (build 19.0-b09, modo mixto) ' –

0

Parece que los métodos "volátiles" son producidos bajo el capó por el compilador de Java, como "métodos de pegamento" para los métodos genéricos. Generics producirá bajo los métodos hood que aceptará solo Object como parámetros y los convertirá al tipo genérico específico, mientras que estos métodos son invisibles para el desarrollador. Sin embargo, hay una manera más segura de determinar estos métodos, usando el method.isBridge()

Cuestiones relacionadas