Carregador de classe Java
Java ClassLoader é uma classe abstrata. Pertence a um java.lang pacote. Carrega classes de diferentes recursos. Java ClassLoader é usado para carregar as classes em tempo de execução. Em outras palavras, a JVM executa o processo de vinculação em tempo de execução. As classes são carregadas na JVM de acordo com a necessidade. Se uma classe carregada depender de outra classe, essa classe também será carregada. Quando solicitamos o carregamento de uma classe, ele delega a classe ao seu pai. Dessa forma, a exclusividade é mantida no ambiente de tempo de execução. É essencial executar um programa Java.
java localdatahora
Java ClassLoader é baseado em três princípios: Delegação , Visibilidade , e Singularidade .
Tipos de ClassLoader
Em Java, cada ClassLoader possui um local predefinido de onde carregam os arquivos de classe. Existem os seguintes tipos de ClassLoader em Java:
Carregador de classes Bootstrap: Ele carrega arquivos de classe JDK padrão de rt.jar e outras classes principais. É pai de todos os carregadores de classe. Não tem nenhum pai. Quando chamamos String.class.getClassLoader() ele retorna nulo e qualquer código baseado nele lança NullPointerException. Também é chamado de ClassLoader Primordial. Ele carrega arquivos de classe de jre/lib/rt.jar. Por exemplo, classe de pacote java.lang.
Carregador de classes de extensões: Ele delega a solicitação de carregamento de classe ao seu pai. Se o carregamento de uma classe não for bem-sucedido, ele carrega as classes do diretório jre/lib/ext ou de qualquer outro diretório como java.ext.dirs. É implementado por sun.misc.Launcher$ExtClassLoader na JVM.
Carregador de classes do sistema: Ele carrega classes específicas do aplicativo da variável de ambiente CLASSPATH. Ele pode ser definido ao invocar o programa usando as opções de linha de comando -cp ou classpath. É filho da extensão ClassLoader. Ele é implementado pela classe sun.misc.Launcher$AppClassLoader. Todo Java ClassLoader implementa java.lang.ClassLoader.
Como funciona o ClassLoader em Java
Quando a JVM solicita uma classe, ela invoca um método loadClass() da classe java.lang.ClassLoader, passando o nome totalmente classificado da classe. O método loadClass() chama o método findLoadedClass() para verificar se a classe já foi carregada ou não. É necessário evitar carregar a classe várias vezes.
Se a classe já estiver carregada, ele delega a solicitação ao ClassLoader pai para carregar a classe. Se o ClassLoader não encontrar a classe, ele invoca o método findClass() para procurar as classes no sistema de arquivos. O diagrama a seguir mostra como o ClassLoader carrega classes em Java usando delegação.
Suponha que tenhamos uma classe Demo.class específica do aplicativo. A solicitação de carregamento dos arquivos desta classe é transferida para o Application ClassLoader. Ele delega ao seu pai Extension ClassLoader. Além disso, ele delega ao Bootstrap ClassLoader. Bootstrap pesquisa essa classe em rt.jar e já que essa classe não está lá. Agora solicite a transferência para o Extension ClassLoader que procura o diretório jre/lib/ext e tenta localizar esta classe lá. Se a classe for encontrada lá, o Extension ClassLoader carrega essa classe. O aplicativo ClassLoader nunca carrega essa classe. Quando a extensão ClassLoader não a carrega, o Aplicativo ClaasLoader a carrega de CLASSPATH em Java.
O princípio da visibilidade afirma que o ClassLoader filho pode ver a classe carregada pelo ClassLoader pai, mas vice-versa não é verdade. Isso significa que se o Application ClassLoader carregar Demo.class, nesse caso, tentar carregar Demo.class explicitamente usando a extensão ClassLoader lançará java.lang.ClassNotFoundException.
De acordo com o princípio da exclusividade, uma classe carregada pelo pai não deve ser carregada novamente pelo Child ClassLoader. Portanto, é possível escrever um carregador de classes que viole os princípios de delegação e exclusividade e carregue a classe por si só.
Resumindo, o carregador de classes segue a seguinte regra:
- Verifica se a classe já está carregada.
- Se a classe não estiver carregada, peça ao carregador de classe pai para carregar a classe.
- Se o carregador de classes pai não puder carregar a classe, tente carregá-la neste carregador de classes.
Considere o seguinte exemplo:
public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } }
Compile e execute o código acima usando o seguinte comando:
javac Demo.java java -verbose:class Demo
-verbose:classe: É usado para exibir informações sobre classes que estão sendo carregadas pela JVM. É útil ao usar o carregador de classes para carregar classes dinamicamente. A figura a seguir mostra a saída.
Podemos observar que as classes de tempo de execução exigidas pela classe da aplicação (Demo) são carregadas primeiro.
Quando as aulas são carregadas
Existem apenas dois casos:
- Quando o novo código de bytes é executado.
- Quando o código de bytes faz uma referência estática a uma classe. Por exemplo, Sistema.out .
Carregamento de classe estático vs. dinâmico
As classes são carregadas estaticamente com o operador 'novo'. O carregamento dinâmico de classes invoca as funções de um carregador de classes em tempo de execução usando o método Class.forName().
Diferença entre loadClass() e Class.forName()
O método loadClass() carrega apenas a classe, mas não inicializa o objeto. Enquanto o método Class.forName() inicializa o objeto após carregá-lo. Por exemplo, se você estiver usando ClassLoader.loadClass() para carregar o driver JDBC, o carregador de classes não permitirá carregar o driver JDBC.
O método java.lang.Class.forName() retorna o objeto de classe acoplado à classe ou faz interface com o nome da string fornecido. Ele lança ClassNotFoundException se a classe não for encontrada.
Exemplo
Neste exemplo, a classe java.lang.String é carregada. Ele imprime o nome da classe, o nome do pacote e os nomes de todos os métodos disponíveis da classe String. Estamos usando Class.forName() no exemplo a seguir.
Aula: Representa um objeto Class que pode ser de qualquer tipo (? é um curinga). O tipo Class contém metainformações sobre uma classe. Por exemplo, o tipo de String.class é Class. Use Class se a classe que está sendo modelada for desconhecida.
getDeclaredMethod(): Retorna uma matriz contendo objetos Method refletindo todos os métodos declarados da classe ou interface representada por este objeto Class, incluindo acesso público, protegido, padrão (pacote) e métodos privados, mas excluindo métodos herdados.
getNome(): Ele retorna o nome do método representado por este objeto Method, como uma String.
import java.lang.reflect.Method; public class ClassForNameExample { public static void main(String[] args) { try { Class cls = Class.forName('java.lang.String'); System.out.println('Class Name: ' + cls.getName()); System.out.println('Package Name: ' + cls.getPackage()); Method[] methods = cls.getDeclaredMethods(); System.out.println('-----Methods of String class -------------'); for (Method method : methods) { System.out.println(method.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Saída
Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access0 access0