Jump to content

Recommended Posts

Posted

Bom dia,

Tenho uma questão para a qual estou a ter dificuldades em encontrar uma resposta "aceitável". Preciso de destruir um objecto, sem ter de esperar que a JVM o faça. Estou a usar a seguinte forma, mas não está a funcionar.

meuobjecto=null;
System.gc();

Existe alguma forma de destruir o objecto, tipo o ".dispose();" do .net ??

Cordiais cumprimentos,

Apocsantos

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Posted

Não há qualquer "dispose", aliás, não há qualquer noção de "destruir um objecto".

Se não precisas da referência coloca-a a null, o GC irá fazer o trabalho dele quando o objecto puder ser removido.

Há alguma razão especial para quereres explicitamente remover um objecto da memória?

Posted

A única maneira de destruir o objeto no momento é da maneira como fizeste. Mas repara que se tiveres mais referencias para o objeto em questão ele não vai ser destruído.

"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Posted

Boa tarde,

Para libertar de imediato o nome do objecto. Isto foi pedido num trabalho académico. Daí ter procurado, e como não encontrei nenhuma forma de o fazer sem ser por "null" e deixar o gc fazer o seu trabalho, lembrei-me de questionar cá.

Não é para usar em ambientes de produção, é mesmo para um trabalho de faculdade, nada mais.

Cordiais cumprimentos,

Apocsantos

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Posted

A própria idea de libertar de imediato está errada quando aplicada em Java. Se colocares todas as referências null e invocares o GC explicitamente como estás a fazer, a JVM não te dá qualquer garantia que o GC vá ser executado. Esse método apenas serve para pedir à JVM que invoque o GC quando tiver possibilidade, resumindo, não tens forma nenhuma de libertar memória quando queres, a única solução é remover todas as referências para um objecto e, com ou sem pedido ao GC, esperar que a JVM proceda à libertação.

Posted

Boa tarde,

Pois eu fiquei com essa ideia após ler a documentação. A questão é que foi exigido o exercício com essa opção no enunciado, sem explicações. Apenas foi sugerido assim, apesar de a meu ver não fazer "ponta de sentido", pois mesmo como estava a tentar, não estava a ir a parte alguma...

O que se pretende é pegar numa resulset e criar objectos com toda ela, para depois invocar um metodo de cada objecto desse tipo. Não foram apresentadas alternativas e possivelmente eu não estou a vê-las, em parte por já estar à bastantes horas a olhar para isto...

Deixo abaixo o exemplo que está a gerar dificuldades.

public void listacarro(String matriculac)throws Exception
   {
    try{
	    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
	    String database =  "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=carros.mdb;";
	    Connection conn = DriverManager.getConnection(database,"","");
	    Statement s = conn.createStatement();
	    String Selcarro = "select * from carros where mastricula = " + "" + matriculac + "";		  
	    s.execute(Selcarro);
	    ResultSet rs = s.getResultSet();
	    Carro x;
	    while ((rs != null) && (rs.next())) {
		    //inicio de nova forma
		    x = new Carro (rs.getInt(1) , rs.getInt(2) , rs.getString(3) , rs.getString(4) );
		    x.imprimeCarro();

		    //Carro (rs.getString(1) = new Carro (rs.getString(1) , rs.getString(2) , rs.getString(3) , rs.getString(4) );			  
		    //fim da nova forma
		    //System.out.println(rs..getString(1) + ":" + rs.getString(2) + ":" + rs.getString(3) + ":" + rs.getString(4));
	    }
	    conn.close();
    } catch (SQLException ex)
    {
	    System.out.println(ex.toString());
    }

Cordiais cumprimentos,

Apocsantos

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Posted

Esse método apenas serve para pedir à JVM que invoque o GC quando tiver possibilidade, resumindo, não tens forma nenhuma de libertar memória quando queres

Errado:

When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

Isto significa que ele faz o melhor possível para limpar a memória. Isso implica que ele irá apagar todos os objetos (sem exceção) que não tenham referencias a apontar para eles.

"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Posted (edited)

Fazer o melhor possível também incluí fazer nada 🙂 , curiosamente, até é a documentação desse método que parece estar errada e tem até um bug reportado sobre o assunto embora tenha sido esquecido há muito, http://bugs.sun.com/...bug_id=6668279.

Não entrando no certo Vs errado, a questão é que o comportamento desse método é dependente da implementação da JVM, as configurações da mesma, da implementação do algoritmo de GC e de uma panóplia de outras coisas. Sendo até possível desligar o comportando desse método por completo na JVM, resumindo, não há garantias nenhumas sobre o que o métod faz. No melhor dos casos (ou pior) o sistema de GC é activo nesse método e a tua aplicação pára durante uns tempos enquanto todos os objectos são removidos, ou então nada acontece.

Voltando ao tópico a única coisa que vejo nesse código que podia implicar uma libertação de recursos imediata seria fechares o Statement assim que deixas de precisar dele, mas isso é feito quando fechas a ligação à BD... sinceramente não percebo o requisíto do exercício.

Edited by Knitter
Posted

Bom dia,

Depois de mais umas quantas horas a ler, acabei por perceber que o objectivo ou é meramente pedagógico, ou é completamente "absurdo".

Para fazer uma query do tipo select a uma BD, para por exemplo listar apenas um registo, que cumpra uma clausula "when", o Prof, quer que se crie um objecto inteiro, sem valores excepto o que vai ser usado na String que vai ser executada no Statment, ficando depois o "objecto entregue à própria sorte".

Ou eu ainda não entendi bem as coisas e o Sistema Operativo me anda a enganar relativamente aos consumos de memória, ou isto só vai aumentar o consumo efectivo de Ram, sem qualquer utilidade prática!

Será que me podem esclarecer esta duvida ?

Cordiais cumprimentos,

Apocsantos

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Posted

Não é garantido que o consumo aumente assim tanto. O consumo de memória em Java não é simples de contabilizar e há vários factores a ter em conta, se quiseres saber quanta memória está a tua aplicação a usar, realmente, tens de usar um profiler para Java porque o que o sistema operativo reporta é referente a todo o processo da JVM e inclui muitas outras coisas. Por exemplo, é norma que a tua aplicação "consuma" 32MB logo que arranca quando na verdade o espaço real é de alguns KB devido à forma como a JVM gere a memória.

Se vais criar apenas um objecto e o vais reutilizar isso ocupa alguns KB de memória, não é significativo. Se por outro lado vais instanciar objectos para milhões de registos és capaz de consumir memória em quantidades significativas, mas se esses objectos são criados com um âmbito limitado (scope) então a memória será libertada mais depressa, como é o caso de objectos criados em métodos ou blocos delimitados.

Não é bem uma resposta e precisaria de analisar o código que estás a usar para ter mais detalhes, mas isso é algo que podes fazer com um profiler que te irá dizer exactamente quanta memória é ocupada pelos objectos, quanto tempo é usado para a sua iniciação, quando é que o GC actua, etc.

Posted

Bom dia,

Vou ver isso com mais calma. O que se me escapa aqui é que para o mesmo "resultado", posso simplesmente pegar na resultset e fazer o System.out.println(); sem ter de criar por exemplo para uma query com 1000 registos, criar dinamicamente 1000 objectos e invocar o metodo "imprime" que basicamente faz o

System.out.println(this.numero, this.marca, this.matricula, this.ano, this.modelo, this.combustivel, this.kms

, de cada um dos objectos, quando seria mais pratico usar um while e fazer o "System.out.println(rs.getInt(1), ... " em vez de criar 1000 objectos, invocar o mesmo metodo de cada um deles, e depois "deixa-los ao deus dará"...

Posso estar cubicamente enganado, mas não me parece uma boa pratica, neste caso, fazer as coisas assim.

Cordiais cumprimentos,

Apocsantos

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Posted (edited)

Se saíres do scope onde os definiste (que é o teu caso) eles são de-referenciados pelo garbage collector e a memoria que ocupavam pode ser reutilizada pela jvm.

Há que perceber, que quando isso acontece, é sintaticamente impossível de aceder ao objecto. Se o tentares fazer, o teu código não compila. Em C++ é possível apontar para onde te apetecer na memória. Incluindo locais potencialmente perigosos.

Quem programa em C++ está sempre preocupado em libertar recursos manualmente, mas o motivo é simplesmente não terem outra alternativa.

Criar esse objectos desse tipo, frequentemente é criar referencias para outros objectos, não é tão frequente o recurso a cópias. No objecto novo ficas com uma referencia para o objecto que passas, e podes usar essa referencia para causar efeitos colaterais, o que eu não aconselho muito, mas é importante perceber isso porque é fundamentalmente diferente de uma passagem por cópia que é o que fazem os métodos em C++ por defeito.

Quero com esta conversa toda dizer, que andar às voltas com referências não é tão dispendioso como pode parecer à primeira vista.

Edited by pedrotuga
  • Vote 1
Posted

Desculpem o off-topic mas acho isto importante:

mas é importante perceber isso porque é fundamentalmente diferente de uma passagem por cópia que é o que fazem os métodos em C++ por defeito.

Dá para alterar?

Eu sempre achei que era sempre, sem exceção, por valor.

"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.