Vários processos da JVM podem compartilhar memory para classs comuns?

Eu gostaria de executar vários processos Java no meu servidor web, um para cada aplicativo da web. Eu estou usando um framework web (Play) que tem um monte de classs de suporte e arquivos jar, e os processos Java usam muita memory. Um processo de reprodução mostra cerca de 225 MB de memory “residente privada”. (Estou testando isso no Mac OS X, com o Java 1.7.0_05.) O código específico do aplicativo pode ter apenas alguns MB. Eu sei que os aplicativos da web Java típicos são jars adicionados a um processo de servidor (Tomcat, etc), mas parece que a maneira padrão de executar o Play é como um aplicativo / processo independente. Se fossem programas em C, a maioria dos 200 MB seria compartilhada e não duplicada em cada aplicativo. Existe uma maneira de fazer isso acontecer em Java? Eu vejo algumas páginas sobre o compartilhamento de dados de class , mas isso parece se aplicar apenas às classs de tempo de execução principais.

Neste momento e com o Oracle VM, isso não é possível.

Mas eu concordo, seria um bom recurso, especialmente porque Java tem todas as informações necessárias para fazer isso automaticamente.

Do topo do meu chapéu, eu acho que o JIT é a única razão pela qual isso não pode funcionar: O JIT leva em conta o comportamento em tempo de execução. Portanto, se o aplicativo A usar algum código em um padrão diferente do aplicativo B, isso resultará em código assembler diferente gerado no tempo de execução.

Mas então, o “padrão” usual é “com que frequência esse código é usado”. Então, se o aplicativo A chamou algum método com muita freqüência e B não, eles ainda poderiam compartilhar o código porque A já pagou o preço para otimizá-lo / compilá-lo.

O que você pode tentar é implantar vários aplicativos como arquivos WAR em uma única VM. Mas, segundo minha experiência, isso geralmente causa problemas com o código que não limpa corretamente locais de thread ou ganchos de desligamento.

O IBM JDK possui um parâmetro jvm para conseguir isso. Confira @ http://www.ibm.com/developerworks/library/j-sharedclasss/

E isso leva para a próxima etapa: http://www.ibm.com/developerworks/library/j-multitenant-java/index.html

Se você estiver usando um contêiner de servlet com suporte a hosts virtuais (acredito que o Tomcat) você poderá usar o plugin play2-war . A partir do Play 2.1, o requisito de ser sempre o aplicativo raiz será removido, para que você provavelmente possa usar qualquer contêiner de servlet.

Uma coisa a ter em mente é que você provavelmente terá que ajustar o arquivo de guerra para mover o WEB-INF/lib para o diretório lib do seu contêiner de servlet para evitar o carregamento de todas as classs novamente e isso pode afetar seu aplicativo se ele usar singleton ou outras formas de dados compartilhados da class.

O problema de compartilhar memory entre instâncias de JVM é mais urgente em plataformas móveis e, até onde eu sei, o Android tem uma solução bastante inteligente para isso no Zygote: a VM é inicializada e, quando executa o aplicativo, é fork() ed. O Linux usa copy-on-write nas páginas de RAM, portanto, a maioria dos dados não será duplicada.

Portar esta solução pode ser possível, se você estiver rodando no Linux e quiser tentar usar o Dalvik como sua VM (eu vi que há uma porta de trabalho do tomcat na Dalvik). Eu esperaria que isso fosse uma grande quantidade de trabalho, economizando alguns poucos $ s em atualizações de memory.

Intereting Posts