ClassLoader

:wink: , bem galera , de fato realmente ,inclusive aqui , tem varios artigos sobre isso , Mas quanto mais leio e pesquiso mais confuso eu fico . Estou desenvolvendo um projeto e ao longo do percurso varias duvidas surgiram no entanto nenhum se perpetuou tanto como essa e sinceramente nao vejo nenhuma outra saida a nao ser uma consulta direta ! è o seguinte

O programa est√° 99% pronto oque falta e esta dando problema √© um esquema que estou tentando fixar para fazer atualiza√ß√Ķes do programa. Eu nao quero criar uma aplicao para javaws !

As classes foram dividas em dois packages , Sources.jar e Bin.jar , contando com uma classe externa √° loader.class.

Deveria funcionar assim , o loader.class consulta a web e verifica que o hash do Bin.jar é diferente do hash da versao atual e entao faz download do novo package e deleta antigo e entao inicia a aplicacao , Isso nao é o problema fiz numa boa ,o problema é que nao consigo de forma alguma fazer esse loader funcionar . Pra nao ter que escrever muito abaixo to postando algo analogo[color=darkblue] [/color] ao que eu preciso.


arquivos:

C:\pro\packteste\Bin.jar
|__sub1.class
|
|_sub2.class

C:\pro\packteste\principal.class

import Vini.*;

public class principal{
public static void main(String[] args){
sub1 s1 = new sub1();
sub2 s2 = new sub2();
s1.run("Frase 1");
s2.run("Frase 2");
}
}
package Vini;

public class sub1{
public void run(String input){
System.out.println(input);
}
}
package Vini;

public class sub2{
public void run(String input){
System.out.println(input);
}
}

Ao compilar :
crio uma pasta com o nome Vini e jogo la dentro os arquivos sub1.java e sub2.java

e executo o seguinte comando no console:
C:\pro\packteste>javac principal.java

Ok ,compila numa boa em seguida executo:
C:\pro\packteste>java principal

O progrma funciona tambem , mas como eu disse la em cima nao da pra ser assim preciso de uma jar e a duvida aparece aqui:

Crio um arquivo Bin.jar ( pego a pasta Vini e compacto com o zip e renomeio para Bin.jar)
deleto a pasta Vini.

Ao compilar novamente:
C:\pro\packteste>javac -cp Bin.jar principal.java

Sim ,compila perfeitamente outra vez , mas eis que chego ao lugar que ja me fez perder noite de sono
:x :x :x

Agora quando tento executar:
C:\pro\packteste>java principal

[quote]Exception in thread ‚Äúmain‚ÄĚ java.lang.NoClassDefFoundError: Vini/sub1
at principal.main(principal.java:5)
[/quote]

ou

C:\pro\packteste>java -cp Bin.jar principal


√ą isso ai , poxaa alguem podia me dar uma forca , nao tenho muita exeperiencia com packages , lendo pela net penso que eu deveria criar um classloader ,porem ja li tantoo a respeito e mesmo assim nao consegui fazer um. Se alguem puder postar um codigo de um classloader que funcione nesse exemplo analogo que eu citei ja √© o suficiente , ou se nao propor algo melhor.

Vc precisa implementar seu proprio classloader ( o que parece que já fez) e associá-lo à thread principal.
Ou seja, a primeira instru√ß√Ķa no main dever√° ser o registro do seu class loader no class loader corrente

[quote=sergiotaborda]Vc precisa implementar seu proprio classloader ( o que parece que já fez) e associá-lo à thread principal.
Ou seja, a primeira instru√ß√Ķa no main dever√° ser o registro do seu class loader no class loader corrente[/quote]

kra , nem precisou , olha só como a solucao era simples:

:hauhau: :idea:

Como eu so burro !
aff como eu nao tinha pensado antes ,vo compra uma caixa de fogos de artificio ! Como algp tao simples me amarrou tanto , rssss , uma dessas aqui tinha que ta no java basico , kkkk

Sinceramente , eu to com dor de cabeça de tanto pensar.

Eis que resolvo deitar pra relaxar e me surge uma idéia :stuck_out_tongue:

Pensei na seguinte logica , quando tento executar
C:\pro\packteste>java -cp Bin.jar principal

eu defino como class-path apenas Bin.jar , ele só vai buscar lah dentro por classes
externas ,entao foi só adicionar a pasta local ao cp … HUAHUA ,putzz
que alivio
ficou assim :

C:\pro\packteste>java -cp Bin.jar;. principal

valeww gente

Ol√°

Parabéns por ter conseguido.

Porém…

Até agora não mostrou ter feito nada melhor do que o Java Web Start.

Mas em compensação, pode estar no caminho de resolver um problema muito grave do Java Web Start, mesmo quando a gente separa os jars e usa o jardiff.

O Java Web Start simplesmente envia uma atualiza√ß√£o do jar sempre que h√° uma vers√£o mais nova no servidor. Mas isto de maneira inteiramente burra pois n√£o permite selecionar os clientes que receber√£o atualiza√ß√Ķes e cria a possibilidade do servidor ser derrubado com todos os clientes querendo atualizar ao mesmo tempo. Isto acontecia no Banco Postal quando todas as milhares de ag√™ncias iniciavam os servi√ßos e havia uma atualiza√ß√£o nova no servidor.

O que voc√™ precisa fazer √© um esquema de s√≥ liberar as atualiza√ß√Ķes ao mesmo temo para um determinado grupo de clientes. N√£o √© dif√≠cil criar uma solu√ß√£o assim quando se tem no servidor uma tabela com os clientes autorizados a usar o sistema (isto havia no Banco Postal).

[]s
Luca

:? voce tem toda a raz√£o !

mas pensei em algo , veja se considera viavel !

junto do hash do arquivo novo , fixar também a data !

e no periodo de uma semana fazer rodizio durante 10 horas do dia com as 10 possiveis terminacoes dos IPs.
E mesmo que o usuario esteja fora da hora que pode fazer update emite alerta falando sobre a atualizacao e
o horario que ele pode carregala.

Se um rodizio do ultimo numero do IP ainda causar problemas ,pode-se ainda pegar os 2 ultimos numeros e no periodo de 1 semana distribuir os dias e ou horas .

ou um misto dos 2 .

Ol√°

Na verdade quando eu passei por estes problemas, surgiram outras idéias mas achei esta sua muito boa. Dependendo do tamanho do seu problema pode resolver perfeitamente.

Mesmo um pequeno supermercado pode parar se todos os terminais de caixa atualizarem o sistema ao mesmo tempo. O Dr Mauro Marinilli já alertava para esta falha do Java Web Start em seu livro Java Deployment with JNLP and webstart de setembro de 2001 (justo quando foi lançado o JWS). Até hoje ninguém da Sun tentou resolver o problema de modo efetivo e sobra para a gente fazer estes esquemas de carregamento de classes na raça com ClassLoaders customizados.

[]s
Luca

:?:

Porque eu gostaria que os clientes derrubassem o servidor ?

Se as classes do cliente e do servidor n√£o s√£o da mesma vers√£o isso gerar√° uma exception na serializa√ß√£o o que deve ser interpretado como uma mudan√ßa de vers√£o pela aplica√ß√£o cliente, o que significa que o usu√°rio deve sair e retornar √† aplica√ß√£o. Sendo que as aplica√ß√Ķes cliente n√£o rodam 24/7 se a atualiza√ß√£o do servidor for fora de expediente n√£o acontece nenhum problema: a vers√£o do cliente ser√° sempre a mais atual.
Eu uso o JWS e n√£o entendi o problema que vc explicou. Poderia esclarecer ?

Ol√°

Imagina que na 6a feira a noite ou no fim de semana você coloca uma nova versão no servidor.

Na segunda pela manh√£, no inicio do hor√°rio comercial em que todos abrem suas aplica√ß√Ķes, o JWS percebe que h√° uma nova vers√£o no servidor e ent√£o come√ßa um download. Todos os downloads come√ßam mais ou menos na mesma hora.

O servidor tenta atender a todos os downloads simult√Ęneos mas √© claro que n√£o d√° conta. Todos os downloads ficam lentos porque a largura de banda e a capacidade do servidor n√£o foram dimensionados para atender os raros casos de downloads de instala√ß√£o.

Aí, o funcionário que tenta usar a aplicação percene que está demorando para abrir e pensa que o download travou. O que faz? Reinicializa a máquina (isto acontecia com o dezenas ou centenas de agências do Banco Postal. O cluster penava apesar da gigantesca largura de banda do servidor)

Resultado: os downloads precisam ser reiniciados e o servidor na maldita 2a feira fica uma tartaruga e o cliente lembra logo do SLA, etc. e tal.

Este gravíssimo problema ficou claro desde o lançamento do JWS em setembro de 2001. A correção passa pelo caminho que o nosso amigo está adotando de fazer um ClassLoader customizado e não usar o JWS. Veja o livro que indiquei no post anterior com outras idéias e discussão ampla do assunto.

Se o JWS for usado por alguma aplicação que não precise ser aberta simultaneamente, então este problema talvez nem seja percebido.

[]s
Luca

[quote=Luca]Ol√°

Imagina que na 6a feira a noite ou no fim de semana você coloca uma nova versão no servidor.
(…)
[/quote]

Entendi, é um problema de carga do servidor. Mas, sendo assim, não é mais facil alterar o servlet que fornece os dados ? Essa lógica de controle de horário e IP etc, poderia ser feita no servidor, negando o update. Isso obriga o JWS a começar depois. Ok, a solução não é muito limpa, mas é melhor que reinventar a roda. Não?

Depois de responder me ocurreu que o problema poderia ser resolvido com um instalador customizado
(passado na tag ) e/ou usando o DownloadService (mais ou menos seguindo a linha em http://forum.java.sun.com/thread.jspa?threadID=5173345&tstart=255 ) .N√£o ?

Ol√°

O JWS não tem este ajuste fino. Para reescalonar os downloads de acordo com o MacAddress (IP nem sempre serve) é preciso uma solução de instalador customizado.

√Č disso que estamos tratando desde o in√≠cio da thread.

Um dos passos mais dif√≠ceis em termos de programa√ß√£o √© justamente entender como o Java carrega as classes. √Č poss√≠vel criar uma solu√ß√£o de instalador customizado que carregue novas classes sem precisar reinicializar o cliente. O modo de trabalho do Erlang √© prof√≠cuo em id√©ias neste sentido.

[]s
Luca

Ol√°

Legal ter trazido este link para a discuss√£o.

Sem nada a ver com o nosso tópico mas com tudo a ver com atualização de software, trago um link de hoje:
Microsoft Updates Both XP and Vista Without User Permission or Notification em http://www.schneier.com/blog/archives/2007/09/microsoft_updat.html

[]s
Luca

[quote=Luca]Ol√°

O JWS não tem este ajuste fino. Para reescalonar os downloads de acordo com o MacAddress (IP nem sempre serve) é preciso uma solução de instalador customizado.
[/quote]

O JWS padr√£o da sun n√£o tem, mas o Servlet que ela usa pode ser extendido.
Não ha necessidade de diferenciar os IP nem os Mac. Se a máquina X tenta atualizar-se e eu nego essa atualização ela vai tentar de novo mais tarde. Ela vai ocncerteza fazer isso porque sem o update o JWS não funciona. Se eu permito apenas um numero limitado de updates por vez , não interessa as máquinas que os estão fazendo.
Outra forma de negar o update é por um servlet no endereço dos recursos que controla os respetivos downloads.
Todos os clientes têm que fazer o update dos mesmos arquivos e o fazem na mesma ordem (por cusa do arquivo jnlp), não interessa quem faz primeiro , nem que os arquivos estejam indo para o mesmo cliente.

Eu sei. Eu estou só tentando entender se essa é realmente a solução mais correta.

Ol√°

Como o servlet entende que é para fazer o download de uns e não de outros? O .jnlp é um recurso estático cujo download não é comamdado pelo servlet.

Se você conseguiu fazer funcionar assim, ppr favor descreva com mais detalhes.

[]s
Luca

[quote=Luca]Ol√°

Como o servlet entende que é para fazer o download de uns e não de outros? O .jnlp é um recurso estático cujo download não é comamdado pelo servlet.

[/quote]

Sim o jnlp é um arquivo cujo download não depende do servlet, mas…

  1. os arquivos que o JWS baixa , cujo endereço está escrito no jnlp , podem passar por um servlet.
  2. o ppr jnlp pode ser gerado dinamicamente.

Se o problema é carga, usem-se mais máquinas. faça-se um cluster. Afinal não é assim que faria se o problema fosse carga do webserver ? Então, mas é exatamente isso o problema que vc descreveu. Um problema de carga do dowload a partir do webserver.
Vc pode impedir sim o dowload do lado do servidor (basta retornar um erro 500). A lógica para isso pode ser variada. Podem limitar por numero (100 downloads simultaneos - não importa o arquivo nem o IP do cliente) ou qq outra logica.
Ou vc pode simplesmente gerar jnlp com url diferenciada. Desta forma os cliente se atualizaram usando diferentes servidores. Afinal é só para isso que interessa usar o jws : deployment remoto.

O que o v_vinicius_v exemplificou √© uma boa se o seu programa √© standalone, ou se vc pode instalar pessoalmente em cada m√°quina. √Č bom para jogos , ou qq programa que precise se auto-atualizar mas n√£o √© a mesma coisa que deployment remoto.
Luca, vc está sugerindo que o classloader que o v_vinicius_v fez é um substituto do jws, mas não é. O jws é mais do que um classloader remoto. Não estou desmerecendo a solução do v_vinicius_v, apenas estou dizendo que o problema de carga que vc referiu pode ser solucionado com jws padrão sem ter que fabricar um classloader especial.

Ol√°

S√©rgio, pelo seu texto desconfio que voc√™ ainda n√£o testou ou ainda n√£o passou pelo problema. Sugiro que fa√ßa um teste. Duvido que n√£o chegue a mesma conclus√£o do que eu, o Vinicius e o Dr Marinilli sobre as limita√ß√Ķes do JWS. S√≥ n√£o retorne erro 500 que pode parar seu cliente.

S√≥ mais uma coisinha. Quando testar monitore a rede. Verificar√° que a largura de banda √© o problema. Pode colocar quantas m√°quinas quiser no seu cluster. Quando passei por estes problemas, o cluster era formado por 2 AIX de √ļltima gera√ß√£o com 16 processadores e 12 Gb de mem√≥ria usando alta disponibilidade. As m√°quinas sempre estiveram longe de esgotar sua capacidade.

[]s
Luca

Entendi.