É possível pré-carregar a JVM para tornar o início de pequenos aplicativos java one-shot mais rápido?

7

Algoritmo esperado:

  1. Você inicia a JVM sem o aplicativo real (apenas informando para carregar alguns jars), carrega e escuta um soquete e aguarda em segundo plano.
  2. Quando você inicia o aplicativo ( preloaded_java -cp /usr/share/java/....jar:. qqq.jar), ele se conecta à JVM carregada existente, carrega jars adicionais (se houver) e executa a classe principal.
  3. preloaded_java apenas rotas de entrada e saída e lida com interrupções etc.

Atualização Implementada uma prova de conceito: http://vi-server.org/vi/code/prejvm/

$ clojure prejvm.clj&
[1] 2883
$ nc 127.0.0.1 7711 <<< '{"mainclass" "test.Hello"}'
$ nc 127.0.0.1 7712
java.lang.ClassNotFoundException: test.Hello
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    ...
    at clojure.main.main(main.java:37)

$ nc 127.0.0.1 7711 <<< '{"classpaths" ["file:///home/vi/code/prejvm/"], "mainclass" "test.Hello"}'    
$ nc 127.0.0.1 7712
Hello, world; number of args is 0
qwe q e32e qda
qwe q e32e qda

$ nc 127.0.0.1 7711 <<< '{"classpaths" ["file:///home/vi/code/prejvm/"], "mainclass" "test.Hello", "argv" ["qqq" "www" "eee"]}'
$ nc 127.0.0.1 7712    
Hello, world; number of args is 3
sdfasdfasf df sad
sdfasdfasf df sad

Atualização 2 : Encontrei a resposta: servidor Nailgun (do VimClojure).

Vi.
fonte

Respostas:

3

Use o servidor Nailgun:

Comece:

java -classpath /usr/share/java/clojure.jar:/usr/share/java/clojure-contrib.jar com.martiansoftware.nailgun.NGServer 127.0.0.1

Use-o:

$ ng clojure.main 
Clojure 1.2.0
user=>

$ ng test.Hello sdf sdf sdf
Hello, world; number of args is 3
sdfsdf
sdfsdf

Pode ser obtido com o VimClojure: http://www.vim.org/scripts/script.php?script_id=2501

Vi.
fonte
Uma leitura rápida não revela nenhum truque do carregador de classes, portanto, uma classe só será inicializada uma vez por execução do servidor e não "por uso". Isso pode ou não afetar a exatidão do que você está executando com o NailGun.
Ken
Se algum código falhar no NailGun por causa disso, provavelmente não está bem escrito. Em um bom programa, "inicializado uma vez por execução de servidor" deveria significar que seria ainda mais rápido.
Vi.
0

Não, o que você descreve não é possível, pelo menos não com a Sun JVM, simplesmente porque ela não está implementada (embora seja uma boa ideia).

No entanto, se você simplesmente executar o aplicativo uma vez, o sistema operacional armazenará em cache os dados na RAM que foi carregada do disco, portanto, as inicializações subseqüentes deverão ser muito mais rápidas. Isso já pode ajudar.

Se você precisa de um aumento de velocidade: você pode, talvez, alterar o aplicativo, de modo que ele continue sendo executado e aceite novas entradas?

scho
fonte
Eu quero uma abordagem mais ou menos universal. Parece que a parte mais complexa será "pseudo-java runner" que lê argumentos e se conecta ao daemon java.
Vi.
"... não é possível, pelo menos não com a Sun JVM" Por que não pode ser aplicativo de terceiros? Todos os recursos necessários já estão presentes na JVM: nosso aplicativo pode carregar a classe e executar main (redirecionando System. {In, out, err}) de alguma forma.
Vi.
É estranho que Sun (/ Oracle) não faça isso, já que tem sido um recurso de várias JVMs de "servidor" desde 1998, aproximadamente.
Daniel R Hicks
0

Claro que isso pode ser feito. O que você descreve é, na verdade, muito parecido com o funcionamento de um servidor de aplicativos Java EE.

jlliagre
fonte
Portanto, deve ser como o servidor de aplicativos Java para programas de console.
Vi.