Cada classe usará seu próprio carregador de classes para carregar outras classes. Então, se ClassA.class
as referências ClassB.class
, em seguida, ClassB
precisa estar no caminho de classe do carregador de classe de ClassA
, ou de seus pais.
O carregador de classe de contexto de encadeamento é o carregador de classe atual para o encadeamento atual. Um objeto pode ser criado a partir de uma classe ClassLoaderC
e depois passado para um thread de propriedade de ClassLoaderD
. Nesse caso, o objeto precisa usar Thread.currentThread().getContextClassLoader()
diretamente se desejar carregar recursos que não estão disponíveis em seu próprio carregador de classe.
ClassB
deve estar no caminho de classe doClassA
carregador (ouClassA
dos pais do carregador)? Não é possívelClassA
substituir o carregadorloadClass()
, de forma que ele possa carregar com êxitoClassB
mesmo quandoClassB
não estiver no caminho de classe?ClassA.class
referênciasClassB.class
"?Isso não responde à pergunta original, mas como a pergunta é altamente classificada e vinculada a qualquer
ContextClassLoader
consulta, acho importante responder à pergunta relacionada de quando o carregador de classes de contexto deve ser usado. Resposta curta: nunca use o carregador de classes de contexto ! Mas defina-o comogetClass().getClassLoader()
quando você precisar chamar um método que está faltando umClassLoader
parâmetro.Quando o código de uma classe pede para carregar outra classe, o carregador de classes correto a ser usado é o mesmo carregador de classe que a classe do chamador (ou seja,
getClass().getClassLoader()
). É assim que as coisas funcionam 99,9% do tempo, porque é isso que a JVM faz na primeira vez em que você constrói uma instância de uma nova classe, invoca um método estático ou acessa um campo estático.Quando você deseja criar uma classe usando reflexão (como desserializar ou carregar uma classe nomeada configurável), a biblioteca que faz a reflexão sempre deve perguntar ao aplicativo qual carregador de classes usar, recebendo o
ClassLoader
parâmetro como do aplicativo. O aplicativo (que conhece todas as classes que precisam ser construídas) deve ser aprovadogetClass().getClassLoader()
.Qualquer outra maneira de obter um carregador de classes está incorreta. Se uma biblioteca usos hacks como
Thread.getContextClassLoader()
,sun.misc.VM.latestUserDefinedLoader()
ousun.reflect.Reflection.getCallerClass()
é um erro causado por uma deficiência na API. Basicamente,Thread.getContextClassLoader()
existe apenas porque quem projetou aObjectInputStream
API esqueceu de aceitar oClassLoader
parâmetro, e esse erro assombrou a comunidade Java até hoje.Dito isto, muitas classes JDK usam um dos poucos hacks para adivinhar o uso de um carregador de classes. Alguns usam o
ContextClassLoader
(que falha quando você executa aplicativos diferentes em um pool de encadeamentos compartilhados ou quando você saiContextClassLoader null
), outros andam na pilha (que falha quando o chamador direto da classe é uma biblioteca), outros usam o carregador de classes do sistema (o que é bom, desde que esteja documentado para usar apenas classes noCLASSPATH
) ou carregador de classes de autoinicialização e alguns usam uma combinação imprevisível das técnicas acima (o que apenas torna as coisas mais confusas). Isso resultou em muito choro e ranger de dentes.Ao usar essa API, primeiro, tente encontrar uma sobrecarga do método que aceite o carregador de classes como parâmetro . Se não houver um método sensato, tente definir a
ContextClassLoader
chamada antes da API (e redefini-la depois):fonte
Existe um artigo no javaworld.com que explica a diferença => Qual ClassLoader você deve usar
(1)
(2) da mesma fonte:
fonte
bootstrap
carregador de classes pai que está sendo definido como o carregador de classes de contexto, mas osystem
carregador de classes de caminho de classe filho com o qualThread
está sendo configurado. AsJNDI
classes estão certificando-se de usarThread.currentThread().getContextClassLoader()
para carregar as classes de implementação JNDI disponíveis no caminho de classe.Adicionando à resposta do @David Roussel, as classes podem ser carregadas por vários carregadores de classes.
Vamos entender como o carregador de classes funciona.
De javin paul blog em javarevisited:
ClassLoader
segue três princípios.Princípio da delegação
O Bootstrap ClassLoader é responsável por carregar os arquivos de classe JDK padrão do rt.jar e é o pai de todos os carregadores de classe em Java. O carregador de classes do Bootstrap não tem nenhum pai.
O Extension ClassLoader delega a solicitação de carregamento de classe ao pai, o Bootstrap e, se malsucedido, carrega o formulário da classe diretório jre / lib / ext ou qualquer outro diretório apontado pela propriedade do sistema java.ext.dirs
Carregador de classe de sistema ou aplicativo e é responsável por carregar classes específicas do aplicativo a partir da variável de ambiente CLASSPATH, da opção de linha de comando -classpath ou -cp, atributo Class-Path do arquivo Manifest dentro do JAR.
Carregador de classe de aplicativo é filho do Extension ClassLoader e é implementado por
sun.misc.Launcher$AppClassLoader
classe.NOTA: Exceto o carregador de classes Bootstrap , que é implementado na linguagem nativa principalmente em C, todos os carregadores de classes Java são implementados usando
java.lang.ClassLoader
.Princípio da visibilidade
Princípio da singularidade
fonte