Duvidas sobre ClassLoader

Galera gostaria de tirar algumas duvidas referentes a classloader.

Sei que primeiramente é inicializado o Bootstrap ClassLoader que da inicio a recursos nativos, posteriormente inicializa o Extension ClassLoader que carrega as API do java, e por ultimo, o Application ClassLoader que carrega tudo aquilo que esta no nosso classpath.

Agora quando eu dou um new em uma classe, o responsável por carregar essa classe por padrão é o Application ClassLoader ?

Outra pergunta, Quando eu crio meu classLoader o próprio Application ClassLoader já inicializa ele para min?

e mais uma duvida, se caso quando darmos um new o Application ClassLoader é responsavel por carregar esta classe e podemos identificar uma classe pelo seu fully qualified name + class loader porque existem casos que a nossa aplicação não consegue localizar uma classe, mesmo ela estando em nosso classpath(tendo em vista que o responsável por carregá-la é o Application ClassLoader)?

Alguém poderia me dar uma explicação de como funciona esse processo de criação da classe no java, suas prioridades de classloader , etc…

Vlw

galerinha, alguem?

Se você simplesmente criou uma classe que extende ClassLoader e não fez nada com ela, ela será só uma classe que não está sendo utilizada.

Para você utilizar um ClassLoader criado por você, você precisa instanciá-lo como qualquer outro objeto e daí pode utilizá-lo para carregar suas classes que não estão no classpath da aplicação.

Ao usar a instrução new você está invocando um construtor da classe, não carregando a classe em si. E sim, as classes instanciadas pela instrução new, foram carregadas pelo Application ClassLoader.

Para você instanciar uma classe que não está no classpath da aplicação, mas que o seu ClassLoader customizado consegue carregar, você precisa utilizar reflection.
Basicamente fazer:

Class<?> classe = meuClassLoaderCustomizado.loadClass("nome binário de sua classe");
// daqui pra frente você usa reflection para instanciar a classe,
// se ela possui um construtor publico sem parâmetros,
// é só fazer o seguinte:
Object instancia = classe.newInstance();
// se possui construtor parametrizado,
// por exemplo que recebe uma String,
// precisa obter uma instancia do construtor desejado
Constructor construtor = classe.getDeclaredConstructor(String.class);
// e aí fazer assim:
Object instancia = construtor.newInstance("conteúdo da String");

Uma observação importante ´q que você não consegue declarar em seu código, classes carregadas dinamicamente.
Imagina que você usou seu ClassLoader customizado para carregar uma classe chamada MinhaClasse, você não poderá escrever um código assim:

// a linha abaixo está OK
Class<?> classe = meuClassLoaderCustomizado.loadClass("MinhaClasse");
// mas a linha abaixo está errada pois o compilador não conhece "MinhaClasse",
// daria erro em tempo de compilação
// MinhaClasse é uma classe dinâmica,
// que só é carregada em tempo de execução pelo seu ClassLoader customizado
MinhaClasse meuObjeto = classe.newInstance();

Como resolver essas situações?
Resposta: usando interfaces (ou classes abstratas, mas eu prefiro interfaces).

Se você criar uma interface na sua API e as classes que você carregar pelo seu ClassLoader customizado implementarem essa interface (ou extenderem a classe abstrata), você pode escrever seus códigos dessa forma:

Class<?> classe = meuClassLoaderCustomizado.loadClass("MinhaClasse");
MinhaInterface meuObjeto = classe.newInstance();
1 curtida

Muito obrigado pelo tempo e pelos esclarecimentos

1 curtida