Exceções de Carregamento de Classe

Que tipo de erro de carregamento de classe você vê ao desenvolver um aplicativo ou iniciar um aplicativo instalado?

ClassCastException

Uma exceção de lançamento de classe ocorre quando as seguintes condições existem e podem ser corrigidas pelas seguintes ações:

O tipo do objeto de origem não é uma instância da classe de destino (tipo).
Essa é a exceção típica de lançamento de classe. É possível diagnosticar se o objeto de origem de uma instrução de lançamento não é uma instância da classe de destino (tipo), examinando a assinatura da classe do objeto de origem, em seguida, verificando se não contém a classe de destino em seu ascendente e a classe do objeto de origem é diferente da classe de destino. É possível obter informações de classe inserindo uma instrução de impressão simples em seu código. Por exemplo:
System.out.println( source.getClass().getName() + : + target.getClass().getName() );
Também é possível utilizar um comando javap. Por exemplo:
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 {
O carregador de classes que carregou o objeto de origem (classe) é diferente do carregador de classes que carregou a classe de destino.
Supondo que o tipo de objeto de origem seja uma instância da classe de destino, uma exceção de lançamento de classe ocorre quando o carregador de classes que carregou a classe do objeto de origem é diferente do carregador de classes que carregou a classe de destino. Essa condição pode ocorrer quando a classe de destino está visível nos caminhos de classe de mais de um carregador de classes no ambiente do tempo de execução do WebSphere Application Server. Para corrigir esse problema, utilize as páginas do console Procurar e Procurar por Nome de Classe utilizadas para diagnosticar problemas com os carregadores de classe:
  1. Clique em Resolução de Problemas > Visualizador do Carregador de Classes > module_name > Procurar para acessar a Página de Procura.
  2. Para Tipo de Procura, selecione Classe/Pacote.
  3. Para Termos de Procura, digite o nome da classe que é carregada por dois carregadores de classe.
  4. Clique em OK. A página Procurar por Nome de Classe é exibida, listando todos os carregadores de classes que carregam a classe.

    Se houver mais de um carregador de classes listado, então, a classe de destino foi carregada por mais de um carregador de classes. Como o objeto de origem é uma instância da classe de destino, o carregador de classes que carregou a classe do objeto de origem é diferente do carregador de classes que carregou a classe de destino.

  5. Retorne para a página Visualizador do Carregador de Classes e examine o caminho de classe para determinar porquê dois carregadores de classe diferentes carregam a classe.
  6. Corrija seu código de forma que a classe esteja visível somente para o carregador de classes apropriado.
O aplicativo falha em executar ou executa incorretamente uma operação de restrição.
Uma exceção de lançamento de classe pode ocorrer pois, quando o aplicativo está resolvendo um objeto EJB (Enterprise JavaBean) remoto, o código do aplicativo não executa uma operação de restrição conforme requerido. O aplicativo deve executar uma operação de restrição após a consulta de um objeto remoto. Examine o aplicativo e determine se ele consulta um objeto remoto e, se esse for o caso, o resultado da consulta é enviado a um método de restrição.

O método de restrição deve ser chamado de acordo com o modelo de programação EJB 2.0. Especificamente, a classe de destino enviada ao método de restrição deve ser a interface exata mais derivada do EJB. Isso também causa uma exceção de lançamento de classe no ambiente de tempo de execução do WebSphere Application Server. Examine o aplicativo e determine se a classe de destino enviada ao método de restrição é uma super interface do EJB especificado, não o tipo exato do EJB; se esse for o caso, modifique o aplicativo para chamar a restrição com a interface exata do EJB.

Por fim, se uma exceção de lançamento de classe ocorrer durante uma operação de restrição, verifique se o método de restrição está sendo aplicado no resultado de uma consulta do EJB remoto, não em um enterprise bean local. Uma restrição não é utilizada para consultas locais. Examine o descritor de implementação do módulo ou aplicativo para assegurar que o objeto que está sendo restringido não é um objeto local.

ClassNotFoundException

A exceção de classe não localizada ocorre quando as seguintes condições existem e podem ser corrigidas nas seguintes ações:

A classe não está visível no caminho de classe lógico do carregador de classes de contexto.
A classe não localizada não está no caminho de classe lógico do carregador de classes associado ao encadeamento atual. O caminho de classe lógico é o acúmulo de todos os caminhos de classe procurados quando uma operação de carregamento é chamada em um carregador de classes. Para corrigir esse problema, utilize a página Procurar para procurar pelo nome de classe e pelo nome JAR (Java™ archive):
  1. Clique em Resolução de Problemas > Visualizador do Carregador de Classes > module_name > Procurar para acessar a Página de Procura.
  2. Para Tipo de Procura, selecione Classe/Pacote.
  3. Para Termos de Procura, digite o nome da classe que não foi localizado.
  4. Clique em OK. A página Procurar por Nome de Classe é exibida, listando todos os carregadores de classes que carregam a classe.
  5. Examine a página para ver se a classe existe na lista.
  6. Se a classe não estiver na lista, retorne à página Procurar. Para Termos de Procura, digite o nome do arquivo .jar para a classe. Para Tipo de Procura, selecione JAR/Diretório.
  7. Clique em OK. A página Procura por Caminho é exibida, listando todos os diretórios que contêm o arquivo JAR.

Se o arquivo JAR não estiver na lista, provavelmente, a classe não está no caminho de classe lógico, não pode ser lida ou uma classe alternativa já foi carregada. Mova a classe para um local que permita que ela seja carregada.

O aplicativo utiliza incorretamente uma API do carregador de classes.
Um aplicativo pode obter uma instância de um carregador de classes e chamar o método loadClass nesse carregador de classes, ou chamar Class.forName(class_name, initialize, class_loader) com esse carregador de classes. O aplicativo pode estar utilizando incorretamente a API (Interface de Programação de Aplicativo) do aplicativo de carregador de classes. Por exemplo, o nome da classe está incorreto, a classe não está visível no caminho de classe lógico desse carregador de classes ou o carregador de classes errado foi empregado.

Para corrigir esse problema, determine se a classe existe e se o aplicativo está utilizando corretamente a API do carregador de classes. Sigas as etapas em A classe não está visível no caminho de classe lógico do carregador de classes de contexto para determinar se a classe está carregada. Se a classe não tiver sido carregada, tente corrigir o aplicativo e ver se a classe é carregada. Se a classe estiver no caminho de classe com permissão apropriada e não estiver sendo substituída por outra classe do depósito de informações do provedor, examine a API utilizada para carregar a classe.

  1. Clique em Resolução de Problemas > Visualizador do carregador de classes > module_name > Procurar para acessar a Página Procurar do carregador de classes.
  2. Para Tipo de Procura, selecione Classe/Pacote.
  3. Para Termos de procura, digite o nome da classe.
  4. Clique em OK. A página Procurar por Nome de Classe é exibida, listando todos os carregadores de classes que carregam a classe.
  5. Examine a página para ver se a classe existe na lista.
  6. Se a classe estiver na lista e uma exceção ClassNotFound tiver sido emitida, o arquivo .jar ou a classe não está no contexto correto ou uma chamada de API errada foi utilizada no contexto atual.
    Se a classe não estiver na lista, retorne à página Procurar e faça o seguinte:
    1. Procure a classe que gerou a exceção; ou seja, a classe que está chamando Class.forName.
    2. Veja qual carregador de classes carrega a classe.
    3. Determine se o carregador de classes tem acesso ou pode carregar a classe não localizada avaliando o caminho de classe do carregador de classes.
Uma classe dependente não está visível.
Quando um carregador de classes clsldr carrega uma classe cls, a JVM (Java Virtual Machine) chama clsldr para carregar as classes das quais cls depende. As classes dependentes devem estar visíveis no caminho de classe lógico de clsldr, caso contrário, ocorre uma exceção. Essa condição geralmente ocorre quando usuários tornam as classes do WebSphere Application Server visíveis ao JVM, ou tornam as classes de aplicativos visíveis ao JVM ou ao carregador de classes de extensões do WebSphere. Por exemplo:
  • A Classe A depende da Classe B.
  • A Classe A está visível para o carregador de classes de extensões do WebSphere.
  • A Classe B está visível no caminho de classe local de um carregador de classes do módulo do WAR, não no caminho de classe do carregador de classes de extensões do WebSphere.

Quando a JVM carrega a Classe A utilizando o carregador de classes de extensões do WebSphere, ela tenta carregar a Classe B utilizando o mesmo carregador de classes e, por fim, cria uma exceção de classe não localizada.

Para corrigir esse problema:

  1. Torne as classes específicas do aplicativo visíveis para o carregador de classes do aplicativo apropriado.
  2. Procure a classe não localizada (Classe B).
  3. Se a Classe B estiver no local apropriado, procure a classe que carrega a classe dependente (Classe A) no Visualizador do carregador de classes.
  4. Se a classe for carregada e uma exceção ClassNotFound tiver sido emitida, o arquivo .jar ou a classe não está no contexto apropriado ou a chamada de API errada foi utilizada no contexto atual.
    Se nenhuma classe tiver sido localizada, faça o seguinte:
    1. Procure a classe que gerou a exceção; ou seja, a classe que está chamando Class.forName.
    2. Veja qual carregador de classes carrega a classe.
    3. Determine se o carregador de classes tem acesso ou pode carregar a classe não localizada avaliando o caminho de classe do carregador de classes.
  5. Assegure que a classe do responsável pela chamada (Classe B) esteja visível para o carregador de classes de extensões do WebSphere ou da JVM.

NoClassDefFoundException

A exceção de definição de classe não localizada ocorre quando as seguintes condições existem e podem ser corrigidas pelas seguintes ações:

A classe não está no caminho de classe lógico.
Consulte ClassNotFoundException para obter informações.
A classe não pode ser carregada.
Há várias razões para a classe não carregar. As razões incluem: falha em carregar a classe dependente, a classe dependente tem um formato inválido ou o número da versão de uma classe.

UnsatisfiedLinkError

Um erro de ligação ocorre quando as seguintes condições existem e podem ser corrigidas pelas seguintes ações:

Uma ação do usuário causou o erro.

Várias ações do usuário podem resultar em um erro de ligação:

Um nome de extensão de biblioteca é incorreto para a plataforma.

[Windows]Uma biblioteca tem o nome de biblioteca de link dinâmico library_name.dll.

[AIX HP-UX Solaris]Uma biblioteca tem o nome library_name.so ou library_name.a.

Um parâmetro incorreto é transmitido a System.loadLibrary.

[Windows]Para carregar uma biblioteca de link dinâmico denominada Name.dll, Name precisa ser transmitido a uma chamada loadLibrary.

[AIX HP-UX Solaris]Para carregar uma biblioteca denominada libName.so ou libName.a, libName é transmitido para a biblioteca de carregamento.

A biblioteca não está visível.
Como uma boa prática, utilize o carregador de classes da JVM para localizar ou carregar as bibliotecas nativas. O WebSphere Application Server imprime o caminho da biblioteca Java (java.library.path) na inicialização. Se o carregador de classes da JVM for utilizado para carregar a biblioteca, verifique se o caminho que contém o arquivo de biblioteca nativa está no caminho da biblioteca Java. Caso contrário, anexe o caminho à variável de ambiente da biblioteca nativa específica da plataforma ou à propriedade do sistema java.library.path da definição do processo do servidor.

Em geral, a Java Virtual Machine chama findLibrary() no carregador de classes xxx que carrega a classe que chama System.loadLibrary(). Se xxx.findLibrary() falhar, a Java Virtual Machine tenta localizar a biblioteca utilizando o carregador de classes da JVM, que procura o caminho da biblioteca da JVM. Se a biblioteca não puder ser localizada, a Java Virtual Machine criará uma exceção UnsatisfiedLinkError.

Assim, se um carregador de classes do WebSphere tiver que localizar uma biblioteca nativa myNativeLib, a biblioteca deverá estar visível no nativelibpath do carregador de classes que carrega a classe que chama System.loadLibrary(myNativeLib). Essa prática é necessária ou desejável na seguinte situação:

  • [z/OS]As bibliotecas nativas para provedores de origens de dados devem estar visíveis no nativelibpath do carregador de classes de extensões do WebSphere. Nesse caso, inclua o caminho que contém a biblioteca nativa na configuração Caminho da Biblioteca Nativa da configuração do provedor de origem de dados.
  • As bibliotecas compartilhadas possuem um Caminho de Biblioteca Nativa em sua configuração. Como as bibliotecas compartilhadas permitem o controle de versões das bibliotecas específicas do aplicativo, considere a especificação dos caminhos para quaisquer bibliotecas nativas utilizadas pelo código de biblioteca compartilhada na configuração da biblioteca compartilhada.

Verifique se o carregador de classes correto do WebSphere carrega a classe que chama System.loadLibrary(), e se a biblioteca nativa está visível na configuração Caminho da Biblioteca Nativa.

[AIX HP-UX Solaris]
System.mapLibraryName retorna o arquivo de biblioteca incorreto.
Ao carregar uma biblioteca compartilhada, a JVM chama mapLibraryName(libName) para converter libName em um nome específico de plataforma. Nos sistemas operacionais AIX, HP-UX ou Solaris, essa chamada pode retornar um nome de arquivo com a extensão errada (por exemplo, libName.so em vez de libName.a). Para depurar isso, grave um programa que chame System.mapLibraryName() e verifique se retorna o nome de arquivo correto.
A biblioteca nativa já está carregada.
Essa condição pode resultar de um dos seguintes erros:
Erro do usuário
Verifique a ocorrência de várias chamadas a System.loadLibrary e remova quaisquer chamadas irrelevantes.
Erro quando um aplicativo é reiniciado
A JVM tem uma restrição de que apenas um carregador de classes poderá carregar uma biblioteca nativa por vez. Um erro ocorrerá quando um aplicativo for reiniciado antes de o coletor de lixo limpar o carregador de classes do aplicativo parado. Quando a classe que carrega a biblioteca nativa é movida, todas as classes que dependem dessa biblioteca nativa e suas dependências também serão movidas.

Para corrigir essa condição, mova o carregamento da biblioteca nativa para um carregador de classes que não está recarregado:

  1. Localize todas as classes de aplicativos que carregam bibliotecas nativas ou possuem métodos nativos.
  2. Identifique quaisquer classes dependentes das classes na etapa 1, como pacotes de criação de log.
  3. Crie uma biblioteca compartilhada associada ao servidor ou uma biblioteca compartilhada isolada.
  4. Mova os arquivos JAR carregados para classes nas etapas 1 e 2 do aplicativo para a biblioteca compartilhada criada na etapa 3.
  5. Salve suas alterações.
  6. Implemente novamente o aplicativo e execute novamente o cenário.

As classes com bibliotecas no escopo do servidor são carregadas uma vez para cada ciclo de vida do servidor, garantindo que a biblioteca nativa necessária pelo aplicativo seja carregada uma vez para cada Java Virtual Machine, independentemente do ciclo de vida do aplicativo.

Uma biblioteca nativa dependente foi utilizada.
As bibliotecas nativas dependentes devem ser localizadas ou carregadas pelo carregador de classes da JVM. Ou seja, se uma biblioteca nativa NL depender de outra biblioteca nativa, DNL, o carregador de classes da JVM deverá localizar a DNL no caminho da biblioteca Java. Isso ocorre porque a JVM executa o código nativo ao carregar a NL; ao encontrar a dependência da DNL, o código nativo da JVM pode chamar somente o carregador de classes da JVM para resolver a dependência. Um carregador de classes do WebSphere não pode carregar uma biblioteca nativa dependente.

Modifique a variável de ambiente específica da plataforma definindo o caminho da biblioteca Java (LIBPATH) para incluir o caminho que contém a biblioteca nativa não resolvida.


Ícone que indica o tipo de tópico Tópico de Referência



Ícone de registro de data e hora Última atualização: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rtrb_classload_viewer
Nome do arquivo: rtrb_classload_viewer.html