Isso não responde à pergunta original, mas como a pergunta é altamente classificada e vinculada a qualquer ContextClassLoaderconsulta, 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 como getClass().getClassLoader()quando você precisar chamar um método que está faltando um ClassLoaderparâ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 ClassLoaderparâmetro como do aplicativo. O aplicativo (que conhece todas as classes que precisam ser construídas) deve ser aprovado getClass().getClassLoader().
Qualquer outra maneira de obter um carregador de classes está incorreta. Se uma biblioteca usos hacks como Thread.getContextClassLoader(), sun.misc.VM.latestUserDefinedLoader()ou sun.reflect.Reflection.getCallerClass()é um erro causado por uma deficiência na API. Basicamente, Thread.getContextClassLoader()existe apenas porque quem projetou a ObjectInputStreamAPI esqueceu de aceitar o ClassLoaderparâ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ê sai ContextClassLoader 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 no CLASSPATH) 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 ContextClassLoaderchamada antes da API (e redefini-la depois):
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
// call some API that uses reflection without taking ClassLoader param
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
ClassBdeve estar no caminho de classe doClassAcarregador (ouClassAdos pais do carregador)? Não é possívelClassAsubstituir o carregadorloadClass(), de forma que ele possa carregar com êxitoClassBmesmo quandoClassBnão estiver no caminho de classe?