BUG no JVM (todas as versoes)

10 respostas
maxguzenski

Seguinte, estou tento esse erro:

java.lang.UnsatisfiedLinkError: Native Library C:WINDOWSSYSTEMOCFPCSC1.DLL already loaded in another classloader
at java.lang.ClassLoader.loadLibrary0(Unknown Source)


causa: tenho um applet que instancia uma DLL… mas quando dou reload na tela, o erro acontece.

procurando na internet, descubri que varias pessoas tiveram o mesmo problema, inclusive no site da sun existe algumas referencias:
http://developer.java.sun.com/developer/bugParade/bugs/4299094.html
http://developer.java.sun.com/developer/bugParade/bugs/4286309.html

conclusao: qq eu faço? reescrevo o ClassLoader oficial :slight_smile:

10 Respostas

Luca

Olá

Todas as linguagens tem suas limitações. Cada applet é carregada com seu próprio classloader e o Plugin Java não permite que uma biblioteca nativa seja carregada por mais de um classloader.

Este problema é curioso e chamou minha atenção. Por favor responda o seguinte:
[list=1:fe874b7a89]1 - Envie para nós o trecho de código onde carrega a dll e a página html que carrega a applet.

2 - É dentro de um bloco estático?

3 - Deu algum resultado colocar no HTML a opção:
<PARAM NAME = “classloader-policy” VALUE=“classic”>

4- Isto só ocorre no IE, certo?[/list:o:fe874b7a89]

Já que estamos falando de applets com permissões além do feijão com arroz, há uma alternativa para bloquear a carga de nova applet e resolver este problema que acho que só ocorre com o IE:
[list=1:fe874b7a89]
Abra um socket com uma porta maluca e só permita abrir a applet se conseguir abrir este socket (q só será possível na primeira vez).[/list:o:fe874b7a89]

Referências:
Bug Id 4873484 - Pressing reload in IE with Applet, reloads in a new ClassLoader - Reported Against 1.4.1, 1.4.2, 1.4.2_03 - closed, fixed - Release Fixed tiger

Bug Id 4642062 - cannot load same DLL from more than one applet in browser - Closed, will not be fixed

[]s
Luca

maxguzenski

1 olha cara, acontece tbm com o MozillaFirebird…

é na API do openCard (www.openCard.org) é uma API pra trabalhar com SmartCards, a chamada nao esta estática, vou recompilar.

2 nao tentei ainda colocar esse parametro na chamada do applet, vo tentar.

3 quanto ao socket, por ser um sistema Web, as pessoas vai precisar abrir o applet varias vezes durante um dia de trabalho, por isso essa solucao nao vai ajudar :slight_smile:

4 Seguinte, se eu abrir o JavaConsole (plugin) e chamar os comandos F (finalize objects) e G (Garbage Collection) e der um reload na pagina, tudo funciona :slight_smile: tem como eu fazer o applet disparar esses comandos no plugin? (tem que ser no plugin, pra que ele posssa limpar os outros classloaders)

dukejeffrie

bom, muita calma antes de sair colocando no fórum avançado que todas as versões da JVM têm bug… é um pouco forte isso…

Também é claro pra mim que vc não precisa de um applet, vc precisa de uma app desktop. Sugiro que vc migre pra WebStart agora mesmo…

Ainda mais pq com Webstart o cara pode colocar um link no desktop dele (ou até no QuickLaunch) e nem abrir o browser… e do mesmo jeito vc mantém todos os benefícios de um applet.

Mas o pau de class loader vai continuar, a menos que vc dê um jeito de saber que a lib já foi carregada. O bloco estático pode (deve) resolver, se vc precisar de alguma mágica com classloaders, no que eu puder ajudar eu tô aqui.

[]s

maxguzenski

entao le:
http://developer.java.sun.com/developer/bugParade/bugs/4299094.html
http://developer.java.sun.com/developer/bugParade/bugs/4286309.html

T

Realmente carregar dll no applet eh um tiro no pe. acredito que a sugestao de usar o Java Web Start seja a melhor saida.

Na verdade o que ocorre eh o seguinte. Quando voce esta navegando , e voce utiliza mais de um applet, a mesma JVM eh utilizada para todos os applets (com outro classloader, para garantir o isolamento), ate para ficar mais rapido e consumir menos memoria. O caso do reload da pagina, infelizmente , eh considerado como um novo applet.

Acontece que seu applet abre uma dll. Ao dar o reload o segundo classloader vai tentar abrir a dll novamente (e nao ha como fazer consulta entre classloaders, para saber se ja foi carregada, sorry).

Carregar duas vezes a dll, para o java, creio que nao seria problematico. Bem, ai eu acredito que ja seja um limitacao do proprio windows. Talvez o windows nao permita que um processo carregue a dll mais de uma vez, teria tipo que descarregar antes de carregar de novo. Talvez em outro so, tipo o linux, poderiamos carregar a mesma Shared Library mais de uma vez. Nao sei bem ao certo se isso seria possivel. Mas o que interessa eh que o problema eh o fato das duas applet (ou a applet depois do reload) tentar carregar novamente a dll

Usando o java web start voce nao vai ter esse problema, primeiro porque voce nao sofrera da acao do reload , afinal, ele eh soh disparado de uma pagina. Segundo porque mesmo que voce dispare mais de uma vez, serao aplicacoes diferentes, JVM diferentes, que podem , independentemente carregar a dll, ja que nao sao o mesmo processo.

dukejeffrie

Bom, eu continuo não achando que é um bug. Se fosse um bug, não ia dar pra vc resolver. E eu acho que dá pra resolver.

Tem um método stop() no applet. A partir dele vc pode limpar tudo, tenta pegar a referência pra sua classe que usa JNI, setar pra null, e chamr um system.gc();

Posso ver o código onde vc chama loadLibrary??

[]s

dukejeffrie

hmmm, nunca pensei nisso… aliás, acho que a menos que um applet seja apenas parte de uma aplicação (e não uma aplicação fechada), não tem mais graça usar… : )

[]s

Luca

Olá

Duke, é um bug, está assinaldo como bug (bug 4873484) e será corrigido no j2sdk 1.5. Este não é o único bug do Java mas neste caso penso como você e também acho que dá para resolver.

Tanque, discordo que carregar dll no applet seja um tiro no pé porque é um dos 2 únicos modos que conheço para fazer uma página html enviar e receber dados de um leitor de smart card que parece que é o caso do Max. Se realmente ele está usando html com applets embutidas então não cabe a solução Java Web Start.

Max, se você sabe que é um bug, ou em outras palavras, por enquanto o Java é assim, por que não adota a sugestão de impedir o reload usando o socket? Há outras maneiras de fazer lock, inclusive com java.nio, mas já usei esta e é bem simples. Além de orientar o usuário que não deve fazer reload, se ele insistir recebe uma mensagem sobre o motivo do bloqueio.

[]s
Luca

maxguzenski

aqui na empresa nao aceitaram problear o reload, preferiram a solucao jws , que ja esta funcionando…

eu vasculhei todo o codigo do ClassLoader, RunTime, e System (aquele arquivo src.zip que vem junto) e achei o erro (tambem entendo que é por questoes de seguranca)

0 ClassLoader, ao chamar uma dll, chama um método privado, chamado loadLibrary0(Class, String);

a classe Classloader, tem um Vector privado que contem a lista de todas as DLL carregadas, inclusive de outros classLoader.

Isso torna impossivel de corrigir, pois nao é possivel herdar a classLoader, pois todos os metodos e variaveis que intenressao sao private…

Logo no inicio do ClassLoader.loadLibrary0 tem um:

if (library.constais(newLibrary) ( {

thrown new UnlinkedException  ;

}

quer dizer, isso com certeza acontece no Linux tbm, ja que nao eh um erro disperado pelo Windows, e sim pela propria classe CLassLoader

Luca

Olá

Beleza!

Então não era uma applet embutida em página html. Sorte sua. Neste caso sempre é melhor adotar JWS mesmo que não seja por este problema.

[]s
Luca

Criado 1 de março de 2004
Ultima resposta 3 de mar. de 2004
Respostas 10
Participantes 4