Pergunta

Eu tenho um carregador de classe personalizado para que uma aplicação desktop pode começar dinamicamente as classes de carga de uma necessidade AppServer I para conversar. Nós fizemos isso uma vez que a quantidade de frascos que são necessários para fazer isso são ridículas (se queria enviá-los). Temos também problemas de versão se não carregar as classes dinamicamente em tempo de execução da biblioteca AppServer.

Agora, eu só bateu um problema onde eu preciso falar com dois AppServers diferentes e descobriram que dependendo cujas aulas eu carregar primeiro eu poderia quebrar mal ... Existe alguma maneira de forçar o descarregamento da classe sem realmente matá a JVM?

Espero que isso faz sentido

Foi útil?

Solução

A única maneira que uma classe pode ser descarregado é se o Classloader utilizado é lixo coletado. Isso significa que as referências a cada classe e ao próprio carregador de classe precisa ir a maneira do dodo.

Uma possível solução para o seu problema é ter um Classloader para cada arquivo jar e um Classloader para cada um dos AppServers que delega a carga real de classes para classloaders Jar específicos. Dessa forma, você pode apontar para diferentes versões do arquivo jar para cada servidor App.

Este não é trivial, no entanto. A plataforma OSGi se esforça para fazer exatamente isso, como cada pacote tem um carregador de classe diferente e dependências são resolvidas pela plataforma. Talvez uma boa solução seria a de tomar um olhar para ele.

Se você não quiser usar OSGI, uma implementação possível seria usar uma instância de JarClassloader classe para cada arquivo JAR.

e criar uma nova, classe MultiClassloader que se estende Classloader. Esta classe internamente teria um array (ou lista) de JarClassloaders, e no método defineClass () iria percorrer todos os carregadores de classe interna até que uma definição pode ser encontrada, ou um NoClassDefFoundException é lançada. Um par de métodos de acesso pode ser fornecido para adicionar novos JarClassloaders para a classe. Há várias implementações possíveis na rede para um MultiClassLoader, então você pode até não precisa escrever o seu próprio.

Se você instanciar um MultiClassloader para cada conexão com o servidor, em princípio, é possível que cada servidor usa uma versão diferente da mesma classe.

Eu usei a idéia MultiClassloader em um projeto, onde as aulas que continha scripts de usuário definidas teve que ser carregado e descarregado da memória e funcionou muito bem.

Outras dicas

Sim, existem maneiras para classes de carga e para "descarregar"-los mais tarde. O truque consiste em implementar o seu próprio carregador de classe que reside entre carregador de classe alto nível (o carregador de classe System) e os carregadores de classe do servidor de aplicativo (s), e esperança de que carregadores de classe do servidor aplicativo que delegar a classloading para os carregadores superiores .

A classe é definida pelo seu pacote, seu nome, e o carregador de classe que originalmente carregada. Programa de um carregador de classe "proxy", que é a primeira que é carregada quando se inicia a JVM. Fluxo de Trabalho:

  • O programa começa e o real "principal" de classe é carregado por este carregador de classe proxy.
  • Cada classe que, em seguida, é normalmente carregado (isto é, não através de uma outra execução do carregador de classe que pode quebrar a hierarquia) vai ser delegadas para este carregador de classe.
  • O proxy delegados classloader java.x e sun.x para o carregador de classe sistema (estes não deve ser carregada através de qualquer outro carregador de classe do que o carregador de classe do sistema).
  • Para cada classe que é substituível, instanciar um carregador de classe (que realmente carrega a classe e não delegá-la ao carregador de classes pai) e carregá-lo por isso.
  • Loja do pacote / nome das classes como chaves e o carregador de classe como valores em uma estrutura de dados (ou seja HashMap).
  • Toda vez que o carregador de classe de proxy recebe um pedido de uma classe que foi carregado antes, ele retorna a classe do carregador de classe armazenados antes.
  • Deve ser suficiente para localizar a matriz de bytes de uma classe por seu carregador de classe (ou para o par "delete" chave / valor de sua estrutura de dados) e recarregue a classe no caso de você quiser mudá-lo.

Feito para a direita lá não deve vir a ClassCastException ou LinkageError etc.

Para mais informações sobre hierarquias carregador de classe (sim, isso é exatamente o que você está execução aqui; -) veja " Java servidor baseado em programação" por Ted Neward - aquele livro me ajudou a implementar algo muito parecido com o que você quer

.

Eu escrevi um carregador de classe personalizada, a partir do qual é possível descarregar aulas individuais sem GCing o carregador de classe. Jar classe Loader

carregadores de classe pode ser um problema complicado. Você pode especialmente ter problemas se você estiver usando vários carregadores de classe e não têm suas interações de forma clara e rigorosamente definido. Eu acho que, a fim de realmente ser capaz de descarregar um youlre classe vai ir tem que remover todas as referências a quaisquer classes (e suas instâncias) que você está tentando se desfazer.

A maioria das pessoas que necessitam de fazer este tipo de final coisa usando OSGi . OSGi é realmente poderoso e surpreendentemente leve e fácil de usar,

Você pode descarregar um ClassLoader mas você não pode descarregar classes específicas. Mais especificamente você não pode descarregar classes criadas em um ClassLoader que não está sob seu controle.

Se possível, eu sugiro usar o seu próprio ClassLoader para que possa descarregar.

classes têm uma forte referência implícita a sua exemplo ClassLoader, e vice-versa. Eles são lixo coletado como com objetos Java. Sem bater as ferramentas de interface ou similar, você não pode remover aulas individuais.

Como sempre você pode obter vazamentos de memória. Qualquer forte referência a uma das suas classes ou carregador de classe vai vazar a coisa toda. Isso ocorre com as implementações Sun de ThreadLocal, java.sql.DriverManager e java.beans, por exemplo.

Se você está assistindo ao vivo se a classe descarga trabalhou em JConsole ou algo, tente também adicionando java.lang.System.gc() no final da sua lógica de classe descarga. Ele aciona explicitamente Garbage Collector.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top