olá galera, estou tendo problema como um jogo q estou fazendo, estou usando o netbeans 6.0 o jogo no emulador do netbeans roda normal, no meu celular rodava normal tb , mas acho q é pq o jogo ficou grande d+ em tempo de execucao baixei o emulador da motorola e no modelo do meu celular (v3) dá erro tb mas rodando em outros aparelhos mais modernos o jogo funfa!, aí olhando os specs sheets dos aparelhos vi um tal de Heap size e vi q do mu aparelho é 800kb enquanto dos outros modelos q rodaram o jogo eram de 1 mega 4 megas e tal é esse valor q determina o tamanho da aplicação em tempo de execução que o celular aguenta? Com isso tudo queria saber se tem como destruir objetos itens que nao vou mais usar, tentei usar o System.gc();, mas nao tive muito sucesso
Grato,
Sim, HeapSize é a “memória RAM” disponível para a sua aplicação.
Provavelmente você está abrindo muitas imagens, além do que o device suporta.
Quando você não precisa mais de uma imagem, remova todas as referências dela. Isso fará com que quando o device chamar o System.gc() automaticamente, ele eliminará essas imagens da memória, liberando para outras.
Por exemplo, se você carregou uma imagem, e guardou-a numa variável, limpe a variável depois que você sabe que não usará mais:
imagem = null;
Tente fazer isso. Verá bons resultados.
[quote=npereirajr]Sim, HeapSize é a “memória RAM” disponível para a sua aplicação.
Provavelmente você está abrindo muitas imagens, além do que o device suporta.
Quando você não precisa mais de uma imagem, remova todas as referências dela. Isso fará com que quando o device chamar o System.gc() automaticamente, ele eliminará essas imagens da memória, liberando para outras.
Por exemplo, se você carregou uma imagem, e guardou-a numa variável, limpe a variável depois que você sabe que não usará mais:
imagem = null;
Tente fazer isso. Verá bons resultados.
[/quote]
Faltou você recomendar que se chame System.gc() logo após liberar a referência.
Desta forma ao invés de esperar a JVM chamar o System.gc(), e isto pode acontecer daqui 1, 5, 10 segundos, sei lá quando…você mesmo dá um toque para ela que seria bom se ela pudesse realizar a faxina agora…
Se a implementação do GC for esperta, verá que uma boa quantidade de memória pode ser liberada e ela então fará isto.
Boone, Não há necessidade de chamar System.gc(), e gastar processamento com uma outra thread, o GC, desnecessariamente.
Quando for necessário, e estiver com pouca memória, automaticamente será chamado o System.gc(), limpando a memória realmente.
Pode fazer o teste. Crie uma tela Canvas, e vá imprindo na tela o total de memória e a memória usada. E crie um timer que a cada 100 milisegundos vai criando uma string e liberando-a, e repintando a tela. Você verá que aos poucos s memória vai sendo usada, e quando chegar num determinado ponto, quando precisar criar um objeto e não houver mais memória, automaticamente o System.gc será chamado, limpando toda a memória.
Abraço,
Só que com isso você joga para a sorte ( tá, não é tão sorte assim ) quando o GC irá rodar e mesmo que você chame System.gc() não garante que ele vá executar ( e nem que ele vá limpar logo na primeira vez, na verdade ele roda duas vezes antes de limpar a memória ). Então o melhor é você se precaver contra isso e ir forçando objetos a serem liberados assim que possível.
Até!
Se você nunca chamar System.gc() você nunca terá problemas. Se você sempre chamar, também nunca terá problemas, mas estará sempre rodando uma thread paralela.
É garantido que quando tem pouca memória seja chamado o System.gc() automaticamente. Não é sorte.
[quote=npereirajr]Se você nunca chamar System.gc() você nunca terá problemas. Se você sempre chamar, também nunca terá problemas, mas estará sempre rodando uma thread paralela.
É garantido que quando tem pouca memória seja chamado o System.gc() automaticamente. Não é sorte.[/quote]
Só que chegamos num problema. Até quando uma memória é suficiente? Ou quando deixar rodar o gc livremente num processamento é boa opção ( antecipar a rodagem do gc antes de um processo é uma questão mais importante do que se ele vai rodar ou não. )? Será que a thread do gc quando chamas é tão inútil ( não esqueçamos que ninguém aqui cria 900 threads num aparelho de mão comum )? Ou mais, deixar lixo sabendo que no futuro ele precisará para o processamento para limpar e com isso dar uma pequena parada que faz com que sua aplicação não fica tão responsiva? Tudo isso para evitar “pedir” para a KVM rodar o System.gc()?
Acho que se você precisa de algo depois e tem capacidade de pedir que adiantem o trabalho, acho que é válido, só não vale rodar 500 vezes o gc.
Até!
Mas se temos certeza de que a memória sempre será limpa quando necessário, não tem porque ficar limpando a memória. Você economiza em linhas no programa, logo em tamanho da aplicação, economiza dinheiro do seu cliente com banda móvel que baixará alguns bytes a menos da sua aplicação, você economiza em tempo do programador que não precisará pensar em quando e onde deverá colocar System.gc(), nem em digitar isso, economiza em processamento, deixa o código mais limpo, sem um monte de System.gc(), etc.
Por isso, decididamente, não é necessário, e se usar ainda estará tendo alguns pequenos problemas como citei.
Economizar bytes (?) e tempo de programador (?!) ao invés de melhorar satisfação do cliente de quando ele estiver mandando a foto do portátil dele que vai ser redimensionado para não tomar banda e no meio do processamento fica lento e faz com que seu sistema pareça lento, apesar de ser bem rápido? Quando falas de código limpo, parece que eu vou mandar uma linha de gc a cada variavel. Falei para sugerir logo que um processamento “pesado” acabe, chame o gc, senão vai enfileirar objetos e você vai depender do gc para rodar ( e eu já dei um exemplo de algo que seria extremamente desagradável de acontecer com o yield do gc ).
Não me concebe fazer código simplório ao invés de analisar no que pode sua aplicação falhar ( não falhar simplesmente mas também deixar lento ).
Até!
Não é lento deixar que a VM faça a limpeza.
Se uma aplicação chama 20 vezes o GC num ciclo de vida para limpar 20 objetos sem referência, mesmo sem necessidade, o tempo gasto é bem maior do que chamar apenas uma vez e nesta única vez ele limpar 20 objetos de uma vez.
Lembre-se que GC é uma thread. E em dispositivos portáteis isso não é trivial. Nesse ambiente, quanto mais pudermos economizar com threads melhor.
Imagine, instanciar, iniciar e controlar 20 threads, procurar objetos sem referência em cada uma delas, e depois fazer a limpeza deles. Isso é mais lento do que instancia apenas 1 vez a thread, inicia-la, procurar os objetos sem referencia e limpá-los.
Em termos práticos com certeza, de longe, a limpeza automática é melhor.
O tempo para limpar todos os objetos sem referência é pouco. Nem se nota. Mas o tempo gasto para chamar o GC num jogo com threads, como é o caso do autor da pergunta, faz muita diferença.
O maior tempo de thread do gc está em mandar todas as outras darem yield do que em se criar uma outra. Maior ainda se as referências a esses objetos não forem fracas (mesmo que os objetos não tenham mais nenhuma variável que a referencie). Criar 20 threads do gc para processar 25 imagens cada é bem melhor do que esperar dar 500 imagens e mandar uma só ( se quiser, teste. Profilers existem para isso ). A probabilidade da GC entrar no meio do processamento é bem alta e isso pode ser um péssimo fator ( caso você abra a conexão a outro dispositivo por http/IP ou outro método que o timeout não seja tão liberal) para a performance.
Usualmente, o uso de System.gc() no meio do código é ineficaz, mas isso está longe de ser regra. Tem pessoas que vivem bem a vida sem rodar alguma vez na vida, há sistemas que se você não fizer isso e demorar mais de 1,5 segundo para responder é claro que perdeste o cliente.
Até!
npereirajr, respeito a sua opnião, mas como lhe disse, chamar System.gc() não é má prática, pelo contrário, se bem usado pode sim ser um aliado para não deixar a aplicação sem memória.
Você deve saber que as implementações da JVM são diferentes entre fabricantes (SonyEricsson, Nokia, Motorola,etc) e em um fabricante também existe diferenças entre modelos…(Nokia 6600, Nokia 2630,etc…).
Não dá para confiar na sorte e esperar o milagre acontecer. Se eu não usar System.gc() vou ter que confiar que a implementação possui um apurado e sofisticado algoritimo que vai prever as necessidades da minha app e vai por isto limpar a memória no momento em que eu quero.
Então, para deixar a coisa meio padronizada entre estas diferentes implementações da JVM, eu “ajudo” a JVM indicando pontos onde seria “de bom grado” que ela fizesse seu papel. Veja, as JVMs vem se modernizando, mas ainda estão longe da tecnologia que hoje é usada no desktop que faz mil peripécias, usa JIT,etc…
Acho sim que chamar System.gc() é uma boa prática de programação, sendo usada com critério e em pontos onde houve recente descarte de muitos objetos (Ex: Um for que criou vários Strings).
E por último, ainda bem que os projetistas do J2ME deram esta opção para a gente, pois imaginavam que justamente pelas diferenças tecnológicas nem imensa fauna de aparelhos, umas implementações são melhores e outras mais ruizinhas, então as melhores podem até se dar o luxo de ignorar a chamada que fizemos com System.gc() enquanto as mais ruizinhas pode “acordar” e dizer “Olha, obrigado pelo toque, vou fazer já a faxina !”.
Há 2 dias atrás, eu estava mexendo em uma app bobinha de tudo que tinha um form e exibia a memória antes e depois do System.gc(). Ela não criava trocentos objetos e nem nada disto. Era pura e simplesmente isto. Após entrar na app no aparelho ela me mostrou que foi reclamado de volta para app 46 Kbytes, ou seja, a app que não faz porcaria nenhuma, conseguiu para si uma memória que por algum motivo ainda não havia sido liberada. Ah, só complementando, eu não havia rodado outra app antes desta fazia um bom tempo, então podemos descartar o efeito de alguma app anterior ter consumido bastante, ter sido terminada e esta memória ter ficado “presa”. O celular também foi desligado antes do upload da app no aparelho.
Enfim, acho que temos opniões antagônicas e por mim continuarei recomendando como boa prática o uso de System.gc() por acreditar,testar e ver seus resultados e ver que pode ser uma aliada ao desenvolvedor que principalmente desenvolve para celulares com heap menores. Atualmente temos heaps de 1Mega ou mais, JARs de tamanho ilimitado,etc…mas quando comecei com J2ME a alguns anos atrás a realidade era MIDP 1.0, heap de 256 KB, JAR de no máximo 30, 40Kb fora outras limitações.Então hoje com aparelhos mais potentes, está mais fácil de abrir mão de System.gc(), mas não em todos os casos, principalmente se a aplicação desenvolvida foi criado pensando na compatibilidade com o MIDP 1.0.
Também respeito a opinião de vocês. Mesmo na prática, programando para um Siemens com heap 128K, nunca foi preciso chamar GC. E olha que eu trabalhava com Canvas e imagens.
Mas é isso aí, não vamos ficar levando isso pra frente 
Abraços.
[quote=npereirajr]Também respeito a opinião de vocês. Mesmo na prática, programando para um Siemens com heap 128K, nunca foi preciso chamar GC. E olha que eu trabalhava com Canvas e imagens.
Mas é isso aí, não vamos ficar levando isso pra frente 
Abraços.[/quote]
Pô, desistiu fácil ? Achei que só de raiva ia escrever um artigo sobre os prós e contras do System.gc() ? :lol:
Hahahaha. Nada. Que dá raiva dá, mas não a ponto de escrever um artigo 
Abraço
nossa pessoal aprendi muito sobre GC, mas ninguem falou de de destruir os objetos um objeto de uma classe por exemplo acho q nao tem como né!?
Grato
ola galera novamente, fiz o lance de colcar null nas images depois q eu nao fosse mais usalas e nao adiantou nada sera pq? agora nao sei o q pode ser pensei q fosse memoria alguma ideia?
Grato
[quote=npereirajr]Pode fazer o teste. Crie uma tela Canvas, e vá imprindo na tela o total de memória e a memória usada.
[/quote]
Como faz isso?