2011-07-13 8 views
28

Obtengo un NoSuchFieldError en mi código, ahora Oracle no es muy claro acerca de por qué se produce este error diciendo solamente: este error solo puede ocurrir en tiempo de ejecución si la definición de una clase ha cambiado de manera incompatible.NoSuchFieldError Java

¿Puede alguien explicarme cómo se podría 'incompatible' cambiar una clase? La clase de la que estoy hablando amplía bastante las clases, así que sospecho que podría tener que ver con eso, pero no sé por dónde empezar a buscar o qué estoy buscando.

+0

Es probablemente ayudaría si incluye un seguimiento de pila o simplemente una sugerencia en lo que intentaste hacer – biziclop

+0

¿puedes publicar algún código? – timaschew

+0

Bueno, tengo una clase de calles LuaUserdata que representa un valor Lua Userdata (puedes olvidarte de lua, no está relacionado) esta clase tiene un campo llamado m_metatable, LuaUserdata se extiende por clase 'a', 'a' extendido por 'b' y eventualmente clasifique 'e' por 'Parte'. Cuando intento acceder al campo m_metatable en 'Parte' obtengo este error, que es extraño ya que el campo no se accede una sola vez en las clases a, b, etc. y todas las clases que se extienden 'd' aún pueden acceder al campo . – Tim

Respuesta

47

Este error generalmente se produce si solo recompila parcialmente su código. Tiene un código antiguo que hace referencia a un campo que ya no existe en los archivos de clase recompilados.

La solución es limpiar todos los archivos de clase y compilar todo desde cero.

Actualización: Si sigue apareciendo el mismo error después de recompilar todo, entonces probablemente esté compilando contra una versión de una biblioteca externa y usando otra en tiempo de ejecución.

Lo que necesita hacer ahora es primero identificar la clase que está causando el problema (parece que ya lo ha hecho) y luego ejecutar su aplicación con la opción de línea de comando -verbose:class. Va a descargar mucha información de carga de clases en su salida estándar y podrá averiguar dónde se carga exactamente la clase problemática.

+0

Hice lo que dijo y limpié/volví a compilar, pero me temo que no resolvió nada – Tim

+0

¿Ha sido útil mi actualización? – biziclop

+0

Sí, cuando comenté la respuesta de Paŭlo, traté de anular algunas clases de una biblioteca y supongo que eso es problemático. ¿Algún consejo sobre cómo reemplazar clases específicas de una biblioteca sin tener que reconstruir toda la biblioteca? No puedo extenderlos solo porque los necesito para extender algo también. – Tim

3

Significa que probablemente ha recompilado una clase que dependía de otra clase ya compilada y no compiló la clase dependiente.

Por ejemplo:

public class MyClass { 
    public int num; 
    public MyClass() { num = 1; } 
} 

public class MyDependingClass { 
    private int foo; 
    public MyDependingClass(MyClass init) { 
     foo = init.num; 
    } 
} 

Así que vuelva a compilar las dos clases, presumiblemente con la mano (un IDE normalmente actualizar el espacio de trabajo del proyecto para que lo que debe manipularse clases dependiendo).

Y funcionó.

Más tarde usted decide refactorizar MiClase:

public class MyClass { 
    private int innernum; 
    public int getNum() { 
     return innernum; 
    } 
    public MyClass() { innernum = 1; } 
} 

Si compila MiClase y no MyDependingClass, al ejecutar su programa y crear una instancia de MyDependingClass por lo que recibirá su NoSuchFieldError.

La corrección a corto plazo es probablemente para recompilar todas las clases en su área de trabajo, lo que debería mostrar el error.

La solución a largo plazo es utilizar Eclipse o NetBeans u otro IDE que maneje esto por usted.

+0

Estoy usando NetBeans y lo recompuse todo, pero no cambió nada – Tim

5

Cuando el compilador compiló el código que arroja el error, había alguna otra clase con un campo, y su clase podría acceder a este campo (ya sea leyendo o cambiando el valor).

En tiempo de ejecución, la otra clase de alguna manera no tiene ningún campo con este nombre, lo que da como resultado el error mencionado.

Una de las razones podría ser que la segunda clase ha cambiado sin que la primera haya sido recompilada. Vuelva a compilar todas sus clases y obtendrá un error de compilación (que le dará más información sobre cómo solucionarlo), o la clase hará referencia a la clase correcta.

Otra razón podría ser que tiene alguna clase en más de un archivo jar (o directorio) en la ruta de la clase (en diferentes versiones), lo que da como resultado que otra clase utilice la clase incorrecta. Revisa todas tus jarras en clases duplicadas.

+0

Su segunda razón probablemente sea mi problema, ya que traté de anular algunas clases de una biblioteca. – Tim

3

Algo a tener en cuenta al rastrear estos errores en un IDE (Eclipse en mi caso) es observar las dependencias de proyectos de los que puede depender su proyecto. Si utiliza diferentes versiones de una biblioteca en diferentes proyectos dependientes, el cargador de ruta de clase puede recoger el incorrecto. Esto incluye que un proyecto dependa de un jar creado a partir de un proyecto de Eclipse, y que otro proyecto dependa de ese proyecto y del proyecto del que se generó el jar. Las clases desactualizadas en el contenedor podrían cargarse potencialmente en lugar de las clases del proyecto.

Ejemplo:

project1 depende de project2 y project3

project3 depende de project2.jar, un frasco generado a partir de los archivos de clase en project2

Se añade un campo estático final a una clase en project2, que se vuelve a compilar, , mientras que project2.jar no se ha reconstruido

Correr project1 puede causar la excepción, ya que las clases de project2 pueden ser cargados desde el proyecto directa o la jarra, que no tiene el campo

+0

Esto es exactamente lo que estoy teniendo en mi proyecto en este momento. Ahora sé dónde mirar. Eres mi salvador, gracias. – Hoto