Excepciones de carga de clases
¿Qué clase de error de carga de clases encuentra cuando desarrolla una aplicación o inicia una aplicación instalada?
ClassCastException
Se produce una excepción de difusión de clase cuando se cumplen las siguientes condiciones y se puede corregir con las siguientes acciones:
- El tipo de objeto de origen no es una instancia de la clase de destino (tipo).
- El cargador de clases que ha cargado el objeto de origen (clase) es distinto del cargador de clases que ha cargado la clase de destino.
- La aplicación no puede realizar o realiza incorrectamente una operación de reducción.
- El tipo de objeto de origen no es una instancia de la clase de destino (tipo).
- Esta es la excepción típica de difusión de clase. Para diagnosticar si el objeto
de origen de una sentencia de difusión no es una instancia de la clase de destino
(tipo), examine la firma de clase de la clase de objeto de origen y, a continuación,
compruebe que no contiene la clase de destino en sus antecesores y que la clase del
objeto de origen es distinta de la clase de destino. Para obtener información de la
clase, inserte una simple sentencia de impresión en el código.
Por ejemplo:
O bien, utilice un mandato javap. Por ejemplo:System.out.println( source.getClass().getName() + “:” + target.getClass().getName() );
javap java.util.HashMap Compiled from "HashMap.java" public class java.util.HashMap extends java.util.AbstractMap implements java.util.Map,java.lang.Cloneable,java.io.Serializable {
- El cargador de clases que ha cargado el objeto de origen (clase) es distinto del cargador de clases que ha cargado la clase de destino.
- Suponiendo que el tipo de objeto de origen es una instancia de la clase de
destino, se produce una excepción de difusión de clase cuando el cargador de clases
que ha cargado la clase del objeto de origen es distinto del cargador de clases que
ha cargado la clase de destino. Esta condición puede ocurrir cuando la clase de
destino está visible en las classpaths de más de un cargador de clases en el entorno
de tiempo de ejecución de WebSphere Application Server. Para corregir este problema, utilice
las páginas de la consola Buscar y Buscar por nombre de clase para diagnosticar los
problemas con los cargadores de clases:
- Pulse página Buscar. para acceder a la
- En Tipo de búsqueda, seleccione Clase/paquete.
- En Términos de búsqueda, escriba el nombre de la clase que cargan los dos cargadores de clases.
- Pulse OK (Aceptar). Aparecerá la página Buscar por nombre de clase, que
incluye todos los cargadores de clases que cargan la clase.
Si hay más de un cargador de clases en la lista, la clase de destino la ha cargado más de un cargador de clases. Como el objeto de origen es una instancia de la clase de destino, el cargador de clases que ha cargado la clase del objeto de origen es distinto del cargador de clases que ha cargado la clase de destino.
- Vuelva a la página Visor de cargadores de clases y examine la classpath para determinar por qué cargan la clase dos cargadores de clases diferentes.
- Corrija el código para que la clase esté visible sólo para el cargador de clases adecuado.
- La aplicación no puede realizar o realiza incorrectamente una operación de reducción.
- Se puede producir una excepción de difusión de clase ya que, cuando la aplicación resuelve un objeto de enterprise bean (EJB) remoto, el código de aplicación no
realiza una operación de reducción tal como es necesario. La aplicación debe
realizar una operación de reducción después de buscar un objeto remoto.
Examine la
aplicación y determine si busca un objeto remoto y, en caso afirmativo, se somete el
resultado de la búsqueda a un método narrow.
El método narrow se debe invocar de acuerdo con el modelo de programación EJB 2.0. En concreto, la clase de destino sometida al método narrow debe ser la interfaz exacta más derivada del EJB. Esto también provoca una excepción de difusión de clase en el entorno de tiempo de ejecución WebSphere Application Server. Examine la aplicación y determine si la clase de destino sometida sometida al método narrow es una superinterfaz del EJB especificado, no el tipo de EJB exacto; en caso afirmativo, modifique la aplicación para invocar narrow con la interfaz de EJB exacta.
Por último, si se produce una excepción de difusión de clase durante una operación narrow, compruebe que el método narrow se esté aplicando al resultado de la búsqueda de EJB remota, no a un enterprise bean local. La reducción no se utiliza en las búsquedas locales. Examine el descriptor de despliegue del módulo o la aplicación para comprobar que el objeto que se está reduciendo no es un objeto local.
ClassNotFoundException
Se produce una excepción de clase no encontrada cuando se cumplen las siguientes condiciones y se puede corregir con las siguientes acciones:
- La clase no está visible en la classpath lógica del cargador de clases de contexto.
- La aplicación utiliza incorrectamente una API de cargador de clases.
- Una clase dependiente no está visible.
- La clase no está visible en la classpath lógica del cargador de clases de contexto.
- La clase no encontrada no está en la classpath lógica del cargador de clases
asociado con la hebra actual. La classpath lógica es la acumulación de todas las
classpaths donde se han realizado búsquedas al invocar una operación de carga en un
cargador de clases. Para corregir este problema, utilice la página Buscar para buscar por el nombre de
clase y por el nombre JAR (Java™ Archive):
- Pulse página Buscar. para acceder a la
- En Tipo de búsqueda, seleccione Clase/paquete.
- En Términos de búsqueda, escriba el nombre de la clase que no se encuentra.
- Pulse OK (Aceptar). Aparecerá la página Buscar por nombre de clase, que incluye todos los cargadores de clases que cargan la clase.
- Examine la página para ver si la clase existe en la lista.
- Si la clase no está en la lista, vuelva a la página Buscar. En Términos de búsqueda, escriba el nombre del archivo .jar correspondiente a la clase; en Tipo de búsqueda, seleccione JAR/directorio.
- Pulse OK (Aceptar). Aparece la página Buscar por vía de acceso, que incluye todos los directorios que mantienen el archivo JAR.
Si el archivo JAR no está en la lista, probablemente la clase no esté en la classpath lógica, no sea legible o ya se haya cargado otra clase alternativa. Cambie la clase a una ubicación que permita cargarla.
- La aplicación utiliza incorrectamente una API de cargador de clases.
- Una aplicación puede obtener una instancia de un cargador de clases e invocar el
método loadClass en ese cargador de clases, o puede invocar nombre_clase, initialize, cargador_clases) con ese cargador de clases. La aplicación puede estar utilizando incorrectamente la
interfaz de programación de aplicaciones (API) del cargador de clases. Por ejemplo,
si el nombre de clase no es correcto, si la clase no está visible en la classpath
lógica de ese cargador de clases, o si se ha involucrado el cargador de clases
incorrecto.
Para corregir este problema, determine si existe la clase y si la aplicación utiliza correctamente la API de cargador de clases. Siga los pasos que se describen en La clase no está visible en la classpath lógica del cargador de clases de contexto para determinar si se ha cargado la clase. Si la clase no se ha cargado, intente corregir la aplicación y vea si se carga la clase. Si la clase está en la classpath con el permiso adecuado y no se ha alterado temporalmente con otra clase de fábrica, examine la API utilizada para cargar la clase.
- Pulse página Buscar del cargador de clases. para acceder a la
- En Tipo de búsqueda, seleccione Clase/paquete.
- En Términos de búsqueda, escriba el nombre de la clase.
- Pulse OK (Aceptar). Aparecerá la página Buscar por nombre de clase, que incluye todos los cargadores de clases que cargan la clase.
- Examine la página para ver si la clase existe en la lista.
- Si la clase está en la lista y se ha generado una excepción ClassNotFound, el
archivo .jar o la clase no está en el contexto correcto o se ha utilizado
una llamada de API incorrecta en el contexto actual.Si la clase no está en la lista, vuelva a la página Buscar y siga estos pasos:
- Busque la clase que ha generado la excepción; esto es, la clase que llama a Class.forName.
- Vea qué cargador de clases carga la clase.
- Determine si el cargador de clases tiene acceso o puede cargar la clase que no se encuentra evaluando la classpath del cargador de clases.
- Una clase dependiente no está visible.
- Cuando el cargador de clases clsldr carga una clase cls, JVM (Java
Virtual Machine) invoca clsldr para cargar las clases de las que depende
cls. Las clases dependientes deben estar visibles en la classpath lógica de
clsldr o se produce una excepción. Esta condición se produce normalmente
cuando los usuarios hacen que las clases de WebSphere Application Server estén visibles para la JVM, o hacen que las clases de aplicación estén visibles para la JVM o para el cargador de clases de extensiones de WebSphere. Por
ejemplo:
- La clase A depende de la clase B.
- La clase A está visible para el cargador de clases de extensiones de WebSphere.
- La clase B está visible en la classpath local de un cargador de clases del módulo WAR, no en la classpath del cargador de clases de extensiones de WebSphere.
Cuando JVM carga la clase A utilizando el cargador de clases de extensiones de WebSphere, intenta cargar después la clase B utilizando el mismo cargador de clases y, en última instancia, genera una excepción de clase no encontrada.
Para corregir este problema:
- Haga que las clases específicas de la aplicación estén visibles para el cargador de clases de la aplicación correspondiente.
- Busque la clase no encontrada (clase B).
- Si la clase B está en la ubicación correcta, busque la clase que carga la clase dependiente (clase A) en el Visor de cargadores de clases.
- Si la clase está cargada y se ha generado una excepción ClassNotFound, el
archivo .jar o la clase no está en el contexto adecuado o se ha utilizado
la llamada de API incorrecta en el contexto actual.Si no se ha encontrado ninguna clase, realice lo siguiente:
- Busque la clase que ha generado la excepción; esto es, la clase que llama a Class.forName.
- Vea qué cargador de clases carga la clase.
- Determine si el cargador de clases tiene acceso o puede cargar la clase que no se encuentra evaluando la classpath del cargador de clases.
- Compruebe que la clase del emisor (clase B) esté visible para la JVM o el cargador de clases de extensiones de WebSphere.
NoClassDefFoundException
Se produce una excepción de no se ha encontrado ninguna definición de clase cuando se cumplen las siguientes condiciones y se puede corregir con las siguientes acciones:
- La clase no está en la classpath lógica.
- Consulte ClassNotFoundException para obtener más información.
- La clase no se puede cargar.
- Existen varias razones para que no se cargue la clase. Las razones incluyen que no se pueda cargar la clase dependiente, que la clase dependiente tenga un formato incorrecto o el número de versión de una clase.
UnsatisfiedLinkError
Se produce un error de enlace cuando se cumplen las siguientes condiciones y se puede corregir con las siguientes acciones:
- Una acción del usuario ha provocado el error.
System.mapLibraryName devuelve el archivo de biblioteca incorrecto.
- La biblioteca nativa ya está cargada.
- Se ha utilizado una biblioteca nativa dependiente.
- Una acción del usuario ha provocado el error.
Varias acciones del usuario pueden provocar un error de enlace:
- Un nombre de extensión de biblioteca es incorrecto para la plataforma.
Una biblioteca tiene el nombre de biblioteca de enlaces dinámicos nombre_biblioteca.dll.
Una biblioteca tiene el nombre nombre_biblioteca.so o nombre_biblioteca.a.
- Se ha pasado a System.loadLibrary un parámetro incorrecto.
Para cargar una biblioteca de enlaces dinámicos denominada Name.dll, se tiene que pasar Name a una llamada de loadLibrary.
Para cargar una biblioteca denominada libName.so o libName.a, se pasa libName a la biblioteca de carga.
- La biblioteca no está visible.
- Como procedimiento recomendado, utilice el cargador de clases JVM para buscar
o cargar las bibliotecas nativas. WebSphere Application Server imprime la vía de
acceso de la biblioteca Java (java.library.path) al arrancar. Si el
cargador de clases JVM está diseñado para cargar la biblioteca, compruebe que la vía
de acceso que contiene el archivo de biblioteca nativa esté en la vía de acceso de
la biblioteca Java. De lo contrario, añada la vía de acceso a la variable de entorno
de la biblioteca nativa específica de la plataforma o a la propiedad del sistema
java.library.path de la definición de procesos del servidor.
En general, la máquina virtual Java invoca findLibrary() en el cargador de clases xxx que carga la clase que llama a System.loadLibrary(). Si xxx.findLibrary() falla, la máquina virtual Java intenta encontrar la biblioteca utilizando el cargador de clases JVM, que busca la vía de acceso de la biblioteca JVM. Si no se puede encontrar la biblioteca, la máquina virtual Java crea una excepción UnsatisfiedLinkError.
De esta forma, si un cargador de clases de WebSphere está diseñado para buscar una biblioteca nativa myNativeLib, la biblioteca debe estar visible en la nativelibpath del cargador de clases que carga la clase que invoca System.loadLibrary(myNativeLib). Este procedimiento es necesario o aconsejable en las siguientes situaciones:
Las bibliotecas nativas de los proveedores de orígenes de datos deben estar visibles en la nativelibpath del cargador de clases de extensiones de WebSphere. En este caso, añada la vía de acceso que contiene la biblioteca nativa al valor Vía de acceso de biblioteca nativa de la configuración del proveedor de orígenes de datos.
- Las bibliotecas compartidas tienen una Vía de acceso de biblioteca nativa en su configuración. Como las bibliotecas compartidas permiten la creación de versiones de bibliotecas específicas de la aplicación, especifique las vías de acceso de las bibliotecas nativas utilizadas por el código de biblioteca compartida en la configuración de biblioteca compartida.
Compruebe que el cargador de clases de WebSphere correcto cargue la clase que llama a System.loadLibrary() y que la biblioteca nativa esté visible en el valor Vía de acceso de biblioteca nativa.
![[AIX HP-UX Solaris]](../images/unix.gif)
- System.mapLibraryName devuelve el archivo de biblioteca incorrecto.
- Cuando se carga una biblioteca compartida, JVM llama a mapLibraryName(libName) para convertir libName en un nombre específico de la plataforma. En los sistemas operativos AIX, HP-UX o Solaris, esta invocación puede devolver un nombre de archivo con la extensión incorrecta (por ejemplo, libName.so en lugar de libName.a). Para depurar este problema, escriba un programa que invoque System.mapLibraryName() y verifique que devuelve el nombre de archivo correcto.
- La biblioteca nativa ya está cargada.
- Esta condición puede deberse a cualquiera de los errores siguientes:
- Error del usuario
- Compruebe la existencia de varias llamadas a System.loadLibrary y elimine toda llamada extraña.
- Error cuando se reinicia una aplicación
- La JVM tiene la restricción de que sólo un cargador de clases puede cargar una biblioteca nativa a la vez. Se producirá un error cuando una aplicación se reinicie antes de que el recopilador de basura limpie el
cargador de clases de la aplicación detenida. Cuando se traslade la clase que carga la biblioteca nativa,
todas las clases que dependan de la biblioteca nativa y sus dependencias también se trasladarán.
Para corregir esta condición, traslade la carga de la biblioteca nativa a un cargador de clases que no se recargue:
- Busque todas las clases de aplicación que carguen bibliotecas nativas o que tenga métodos nativos.
- Identifique cualquier clase dependiente de las clases en el paso 1, como paquetes de anotaciones cronológicas.
- Cree una biblioteca compartida asociada al servidor o una biblioteca compartida aislada.
- Traslade los archivos JAR cargados para clases en los pasos 1 y 2 de la aplicación en la biblioteca compartida creada en el paso 3.
- Guarde los cambios.
- Vuelva a desplegar la aplicación y ejecute de nuevo el escenario.
Las clases dentro de las bibliotecas con ámbito de servidor se cargan una vez en el ciclo de vida de cada servidor, lo que garantiza que la biblioteca nativa necesaria par la aplicación se carga una vez para cada máquina virtual Java, independientemente del ciclo de vida de la aplicación.
- Se ha utilizado una biblioteca nativa dependiente.
- El cargador de clases JVM debe encontrar o cargar las bibliotecas nativas
dependientes. Esto es, si una biblioteca nativa NL depende de otra biblioteca
nativa DNL, el cargador de clases JVM debe encontrar DNL en la vía de acceso
de biblioteca Java. Esto se debe a que la JVM ejecuta código nativo cuando carga NL;
cuando encuentra la dependencia de DNL, el código nativo de JVM sólo puede llamar al
cargador de clases JVM para resolver la dependencia. Un
cargador de clases de WebSphere no puede cargar una biblioteca nativa dependiente.
Modifique la variable de entorno específica de la plataforma al definir la vía de acceso a las bibliotecas Java (LIBPATH) de modo que incluya la vía de acceso que contiene la biblioteca nativa no resuelta.