Agora deixa eu tentar explicar melhor 
O problema é o seguinte, faço chamadas a uma biblioteca nativa por JNI, até ai blz, só q em ambiente multithread, depois de segundos de execução tenho o seguinte erro:
# An unexpected error has been detected by Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x10020136, pid=4608, tid=8160
Um erro da VM, e a aplicação fecha e vai abaixo…
Como contornar isto?
Tentei passar uma única instância da biblioteca para todas as threads, ai funcionou bem, mas ai tenho q executar as threads com synchronized, para uma thread não executar métodos da biblioteca ao mesmo tempo…
Só q isto não resolve o problema, por que preciso de multithreads, e preciso fazer uma instância da biblioteca para cada thread, o que dá o tal errro.
Ai vem a idéia maluca, tem como eu executar as threads em um outro processo, onde caso de erro da VM, não mate a aplicação? Mas este novo processo poder usar as instâncias dos objetos processo base?
Se alguém tiver uma luz :idea:
:twisted:
Valew
a) Você pode usar uma JVM paralela que se comunica com sua aplicação via sockets. Não há uma maneira de compartilhar objetos.
b) Sua biblioteca JNI pode estar com problemas de threading. Foi você que a escreveu?
[quote=thingol]a) Você pode usar uma JVM paralela que se comunica com sua aplicação via sockets. Não há uma maneira de compartilhar objetos.
b) Sua biblioteca JNI pode estar com problemas de threading. Foi você que a escreveu?[/quote]
A)
Eu queria evitar esta de via Socket, que daria um trabalhão implementar isto, pois os objetos depois dentro das threads usam recursos da aplicação base, e teria q mudar muito código pra fazer isto…
B)
É uma biblioteca fechada, não tem como mexer… :evil:
Isto é uma aplicação que já tem um bom tempo e muita coisa por trás, queria saber se existe uma solução simples 
Tipo dizer q as threads xpto podem dar o erro q quiser, derrubar a VM, mas tudo continua na boa :lol:
É pedir de mais né? :x
Bom, eu tenho um livro chamado “J2EE Antipatterns”. Ele diz, explicitamente:
“JNI IS AN ANTIPATTERN”
Ele diz que você deve evitar JNI em aplicações J2EE como a peste, e se não puder evitá-la, fazer rodar o JNI em um executável Java separado que pode ser derrubado à vontade, e que se comunica com sua aplicação J2EE via sockets.
Quando eu falei “sockets” poderia ser RMI - mas não importa; é melhor que fique em um processo paralelo, ou então que você compense os problemas de threading de alguma forma (force o acesso “sequencial” a essa biblioteca JNI, usando “synchronized” ou alguma coisa parecida).
[quote=eduveks]Agora deixa eu tentar explicar melhor 
O problema é o seguinte, faço chamadas a uma biblioteca nativa por JNI, até ai blz, só q em ambiente multithread, depois de segundos de execução tenho o seguinte erro:
# An unexpected error has been detected by Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x10020136, pid=4608, tid=8160
Um erro da VM, e a aplicação fecha e vai abaixo…
Como contornar isto?
[/quote]
Parto do principio que vc não pode se excusar de usar JNI. Suponho que se pudesse, já o teria feito.
Assim sendo, este é um daqules exemplos muito bons de porquê o padrão singleton existe. O singleton resolve o seu problema. Primeiro porque só existirá uma instancia da classe, segundo porque essa instancia fará os suncronized (não tendo que os fazer em cada lugar que chamar o objeto)
Se por alguma razão exotérica vc dicidir que não quer usar o singleton, então use uma fábrica. O ponto é que vc deve ter um codigo que obtenha a instancia do objeto JNI de tal forma que uma vez criado o objeto é sempre o mesmo a ser devolvido.
Outra opção , mas que depende do uso que vc faz do objeto, é usar o padrão produtor-consumidor. Aqui, uma única thread manipula o objecto JNI (logo, não precisa de synchronized). Essa thread recebe as requisições que tem que sumeter ao objeto através de uma fila. Essa é fila é preenchida con requisções de qualquer parte do resto do sistema. (o mesmo pode ser feito para a resposta do JNI)
Este padrão é excelente se o objeto JNI é na realidade um mensageiro, como um socket, uma porta USB ou algo do estilo.
Um exemplo bom do JNI em uma única thread é o próprio Swing, que usa uma única thread para desenhar suas telas. Fazendo isso ele evita problemas com multithreading que ocorrem com vários sistemas operacionais quando se acessam as telas.
Uma coisa parece ser certa: Tuas threads estao acessando ao mesmo tempo a mesma instância dessa biblioteca aí o sistema diz q ela ja esta em uso. Então tente programar o uso dela pela tua aplicação, ou seja, use um recurso do java q são os Timers… assim tu pode programar todos os teus acessos à essa Library, além de ganhar performance.
Idéia:Já que nao pode usar uma nova instancia para cada Thread, Você pode usar uma instância única e fazer uma aplicação que gerencia o seu uso (semáforo) e essa aplicação vai liberando as instâncias para tuas threads, somente quando não estiverem em uso ( pode usar o Timer e TimerTask aí tbm )
Você pode substituir sem muito trabalho, as suas Threads por um Timer, programado por uma TimerTask. é uma tentativa prática…
O Timer pode ser programado para execução em horários determinados (sequencialmente).
Opinião pessoal:
usar um Timer com uma TimerTask é boa. Já fui convencido à mudar para essa implementação para sobrepor uso de threads… e não dá nenhum trabalho, pois são classes simples. Podemos chamar de “thread inteligente” pois são Threads em um nivel mais alto, e que te economiza o uso do servidor. (evita o uso de um sleep)
Exemplinho básico:
Timer timer = new Timer();
TimerTask minhaTimerTask = new MinhaTimerTask();
Long period = new Long("5000");
timer.scheduleAtFixedRate(minhaTimerTask, minhaDataDeInicioa(), period.longValue());
Abraços!
Muito obrigado pelas idéias, mas o problema é muito mais complexo, e a dica do thingol de usar RMI foi o que me salvou desta vez, brigadão thingol.
Resolvi da seguinte forma, primeiro inicio varias instancias da biblioteca em varios processo, e em cada processo inicio o RMI Server, e dou um output com a porta que o RMI Server ficou, to fazendo tentar pegegar num rang de portas, uma porta disponível, e do outro lado pego o output com o número da porta e inicio o RMI Client.
Faço um processo para cada thread, e em cada processo tem uma instância da biblioteca.
Ai depois lá pra dentro de cada thread, invoca os métodos da biblioteca via RMI.
Não posso usar semaforos, por que é preciso que seja executado em simultaneo, e tenho que garantir sincronia, por isso uma instancia para cada thread e não uma instãncia pra todas, uma instância pra todas, eu consegui fazer logo a primeiro, só q isto não resolvia, pois as outras threads tinham q estar a espera da que estava em execução, e a solução exige multithreads no stop. 
Mais uma vez obrigado a todos, e thingol, obrigadão pela luz 
Credo, que solução pesada (20 processos Java - mesmo usando o Java 5.0 ou 6.0 e a opção -Xshare:on, para usar memória compartilhada para uma boa parte das bibliotecas-padrão do Java, fica bem pesado)…
Quem escreveu a DLL (ou .SO) JNI e não levou em consideração o acesso multithread devia levar umas porradas 
[quote=thingol]Credo, que solução pesada (20 processos Java - mesmo usando o Java 5.0 ou 6.0 e a opção -Xshare:on, para usar memória compartilhada para uma boa parte das bibliotecas-padrão do Java, fica bem pesado)…
Quem escreveu a DLL (ou .SO) JNI e não levou em consideração o acesso multithread devia levar umas porradas 
[/quote]
Até q não ficou muito pesado, mas se ficar, então é mudar o servidor :twisted:
E não é preciso 20, uns 10 processos, já dão conta de aguentar o fluxo, mais q isto espera na fila sentado por alguns milésimos… :twisted:
Mas agora esta do -Xshare:on, desconhecia… como uso isto? Passo esta flag, para o processo principal e pros filhos e boa? Eu assim mas não houve ganho de desempenho, na criação dos processo e no kill, ficou tudo na mesma, mas é melhor com isto do que sem isto? heee
Se você usa o Java da Sun, opção “-client” (que é a default em Windows e Linux), e não seleciona algum método esquisito de “garbage collection”, então -Xshare:on é padrão. Isso foi inventado para que você possa ter muitos processos GUI rodando na mesma máquina, compartilhando a memória usada pelas bibliotecas-padrão do Java. Mas no seu caso talvez não seja necessário. (Se você estiver usando “-server” ou tiver modificado as opções de garbage collection, então -Xshare:on não funciona.)
[quote=thingol]Se você usa o Java da Sun, opção “-client” (que é a default em Windows e Linux), e não seleciona algum método esquisito de “garbage collection”, então -Xshare:on é padrão. Isso foi inventado para que você possa ter muitos processos GUI rodando na mesma máquina, compartilhando a memória usada pelas bibliotecas-padrão do Java. Mas no seu caso talvez não seja necessário. (Se você estiver usando “-server” ou tiver modificado as opções de garbage collection, então -Xshare:on não funciona.)
[/quote]
Ok, boa, mais uma pra coleção…
Mas no meu caso então não se aplica, estou usando -server.
Valew!