apocsantos Posted May 17, 2012 at 11:05 AM Report #456357 Posted May 17, 2012 at 11:05 AM 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"
Knitter Posted May 17, 2012 at 11:08 AM Report #456359 Posted May 17, 2012 at 11:08 AM 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?
brunoais Posted May 17, 2012 at 12:46 PM Report #456372 Posted May 17, 2012 at 12:46 PM 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%.
pedrotuga Posted May 17, 2012 at 01:05 PM Report #456379 Posted May 17, 2012 at 01:05 PM Curiosidade minha, porque é que queres destruir um objecto manualmente numa linguagem que tem garbage collection?
apocsantos Posted May 17, 2012 at 01:37 PM Author Report #456391 Posted May 17, 2012 at 01:37 PM 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"
Knitter Posted May 17, 2012 at 02:03 PM Report #456398 Posted May 17, 2012 at 02:03 PM 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.
apocsantos Posted May 17, 2012 at 02:21 PM Author Report #456402 Posted May 17, 2012 at 02:21 PM 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"
brunoais Posted May 17, 2012 at 03:25 PM Report #456425 Posted May 17, 2012 at 03:25 PM 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%.
Knitter Posted May 17, 2012 at 05:36 PM Report #456476 Posted May 17, 2012 at 05:36 PM (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 May 18, 2012 at 09:52 AM by Knitter
apocsantos Posted May 18, 2012 at 09:31 AM Author Report #456603 Posted May 18, 2012 at 09:31 AM 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"
Knitter Posted May 18, 2012 at 09:59 AM Report #456609 Posted May 18, 2012 at 09:59 AM 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.
apocsantos Posted May 18, 2012 at 10:53 AM Author Report #456615 Posted May 18, 2012 at 10:53 AM 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"
pedrotuga Posted May 18, 2012 at 05:02 PM Report #456716 Posted May 18, 2012 at 05:02 PM (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 May 18, 2012 at 05:04 PM by pedrotuga 1 Report
brunoais Posted May 20, 2012 at 01:35 PM Report #456950 Posted May 20, 2012 at 01:35 PM 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%.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now