Garbage Collector - Questão Livro

21 respostas
taaqui

Bem, uma duvida básica sobre garbage collector

<blockquote>public class Dog {

Short story = 200;

Dog go(Dog cd){

cd = null;

System.out.println(o);

return cd;
}

public static void main(String[] args) {

Dog c1 = new Dog();

Dog c2 = new Dog();

Dog c3 = c1.go(c2);

c1 = null;

}
}

Porque a resposta certa seria 2 objetos? Estou altamente confuso com relação a esse código.

21 Respostas

peczenyj

Ja parou para testar quem desses 3 objetos não é null? :wink:

rmendes08

Antes de mais nada … qual é a pergunta ?

rafaelsantos1983

Essa questão é bem parecida com a do livro de Kathy Sierra, só mudando o nome da classe.
Na linha c1 = null, o objeto Dog c1 fica qualificado para o GC. Além dele o objeto Wrapper Short story que é membro de Dog também fica qualificado para o GC.

Vini_Fernandes

Cara, muito simples: o metodo go(Dog d) sempre retorna null, portanto teremos

Dog c3 = c1.go(c2); 
c1 = null;

onde c3 == null, pois o metodo go() sempre retorna null.
Um dos meios que o GC elege um objeto para a coleta e contando quantas referencias esse objeto possue, como c3 == null, entao temos um objeto eleito, e novamente c1 == null tempos outro objeto eleito. Total == 2.

Abracao

taaqui

Vini Fernandes:
Cara, muito simples: o metodo go(Dog d) sempre retorna null, portanto teremos

Dog c3 = c1.go(c2); 
c1 = null;

onde c3 == null, pois o metodo go() sempre retorna null.
Um dos meios que o GC elege um objeto para a coleta e contando quantas referencias esse objeto possue, como c3 == null, entao temos um objeto eleito, e novamente c1 == null tempos outro objeto eleito. Total == 2.

Abracao

Eu entendi porque o C1 está nulo, mais no livro diz que tem algo a ver com a variável story, ou seja que a variável story esta recebendo nulo ou algo do género, mais o rafaelsantos1983 respondeu certinho que deu para entender, vlw obrigado.

G
public class Dog { 
	
Short story = 200; 
Dog go(Dog cd){ 
cd = null; 
System.out.println("Dentro do metodo, cd: " + cd); 
return cd; 

} 
public static void main(String[] args) { 
Dog c1 = new Dog(); 
Dog c2 = new Dog(); 
Dog c3 = c1.go(c2); 
c1 = null; 
System.out.println("C1: " + c1);
System.out.println("C2: " + c2);
System.out.println("C3: " + c3);

} 
}

resultado:
Dentro do metodo, cd: null
C1: null
C2: Dog@3e25a5
C3: null

Quando esta nulo nao quer dizer que esta disponivel para ser coletado? nao entendi…

Jeferson_Manetti

olá pessoas…

bora lá…

public class Dog { 
	
Short story = 200; // isso aqui e um obj, certo?

// aqui recebe uma copia da variavel... isso mesmo copia...
// portanto cd = null; NÃO vai marca o obj c2 como null... certo?
Dog go(Dog cd){ 
cd = null; 
System.out.println("Dentro do metodo, cd: " + cd); 
return cd; // sempre retorna null;

} 
public static void main(String[] args) { 
Dog c1 = new Dog(); // 1 obj
Dog c2 = new Dog(); // 2 obj
Dog c3 = c1.go(c2); // aqui não crio nd... tenho apenas uma variavel de referencia com valor null..
c1 = null; 
/*
Conclusão... temos:
c1 == null
c2 == Dog@1234
c3 == null

o obj referenciado pelo c1 não pode ser alcançado por nehum Thread, portanto temos um obj pra o GC
só q dentro do obj c1 tinha um obj Short, lembra? 
como não alcanço o obj tambem não vou conseguir alcançar o Short..

Dai temos 2 obj para o GC

como c3 não criou nenhum obj... não vai ter nenhum obj pra o GC

e c2 esta firme e forte no lugar dele...

isso foi oq eu entendi disso tudo ^^

*/

} 
}
G
Jeferson_Manetti:
olá pessoas... bora lá...
public class Dog { 
	
Short story = 200; // isso aqui e um obj, certo?

// aqui recebe uma copia da variavel... isso mesmo copia...
// portanto cd = null; NÃO vai marca o obj c2 como null... certo?
Dog go(Dog cd){ 
cd = null; 
System.out.println("Dentro do metodo, cd: " + cd); 
return cd; // sempre retorna null;

} 
public static void main(String[] args) { 
Dog c1 = new Dog(); // 1 obj
Dog c2 = new Dog(); // 2 obj
Dog c3 = c1.go(c2); // aqui não crio nd... tenho apenas uma variavel de referencia com valor null..
c1 = null; 
/*
Conclusão... temos:
c1 == null
c2 == Dog@1234
c3 == null

o obj referenciado pelo c1 não pode ser alcançado por nehum Thread, portanto temos um obj pra o GC
só q dentro do obj c1 tinha um obj Short, lembra? 
como não alcanço o obj tambem não vou conseguir alcançar o Short..

Dai temos 2 obj para o GC

como c3 não criou nenhum obj... não vai ter nenhum obj pra o GC

e c2 esta firme e forte no lugar dele...

isso foi oq eu entendi disso tudo ^^

*/

} 
}

blz cara eu entendi que ele passou uma copia da referencia pro argumento do metodo, e que o c3 nao criou objeto nenhum porque nao foi instanciado com o new certo?

agora.. como assim "obj c1 tinha um obj Short", aonde aconteceu isso que eu nao to entendendo?

rafaelsantos1983

Isso acontece nesse linha:

Dog c1 = new Dog();

Quando o objeto c1 do tipo Dog é criado(ou seja instânciado) o membro da classe(story) também é criado e instânciado porque ele já tem valor igual a 200.

Ou seja dois Objetos, o c1 do tipo Dog e o story do tipo Short.

G

rafaelsantos1983:
Isso acontece nesse linha:

Dog c1 = new Dog();

Quando o objeto c1 do tipo Dog é criado(ou seja instânciado) o membro da classe(story) também é criado e instânciado porque ele já tem valor igual a 200.

Ou seja dois Objetos, o c1 do tipo Dog e o story do tipo Short.

e o c2 quando eh instanciado? ele nao faz nada com o objeto story? entao quer dizer que eu criando varios objetos digamos, int i = 1, Long l = 2, vao ser criados assim que o c1 for instanciado? nao to sacando isso muito bem…

rafaelsantos1983

Quando c2 é criado(ele é outro objeto, diferente de c1) um outro objeto story é criado, porque c2 foi instanciado.
Se story fosse static seria apenas um unico objeto para todas as instancias, mas não é o caso.

Sim, se vc colocar outro atributo na classe Dog(tipo Long e ele já sendo instanciado, seja usando new ou usando boxing), ele será mais um outro objeto a ser colocado no HEAP.

int não, por que int é tipo primitivo, ficará na pilha.

G
public class Dog { 
Short story = 200; 
Long long = 1; //mais um objeto
Dog go(Dog cd){ 
cd = null; 
System.out.println("o"); 
return cd; 

} 
public static void main(String[] args) { 
Dog c1 = new Dog(); // entao aqui no caso o c1 eh instanciado e e cria o story e o long junto com ele, certo?
Dog c2 = new Dog(); //aqui a mesma coisa o c2 eh instanciado e cria outro story e long com ele?
Dog c3 = c1.go(c2); 
c1 = null; //aqui entao, os objetos que foram criados com c1 que no caso, story e long e o proprio c1 tambem recebem nulo, certo? ( no caso 3 )e os objetos story e long do c2 sao outra historia? e nao recebem o valor de nulo porque o c2 continua "vivo" certo?


} 
}
rafaelsantos1983

Quem recebeu null foi c1, não story e nem long(ps: long é palavra privada, não pode ser usado como nome de atributo, método), mas também perderam a referência, já que o c1 perdeu a referência.

G

ahh eh verdade… escrevi long sem saber… mas entao, quem recebeu null foi o c1, entao agora o c1 esta sem referencia nenhuma entao pode ser coletado, e o story e o objeto “l” Long? tambem estam disponiveis para serem coletados? poruqe? cara foi mal eh que eu to apanhando muito pra isso… sei que eh besteira.

rafaelsantos1983

hehee num é besteira não… também apanhei nesa questão quando estava estudando GC.

Mas pelo o que estudei, quando um objeto fica disponível para o GC, os seus membros(atributos) que são objetos também ficam disponíveis.
Não sei falar técnicamente esse assunto, mas a explicação é ± assim.

G

rafaelsantos1983:
hehee num é besteira não… também apanhei nesa questão quando estava estudando GC.

Mas pelo o que estudei, quando um objeto fica disponível para o GC, os seus membros(atributos) que são objetos também ficam disponíveis.
Não sei falar técnicamente esse assunto, mas a explicação é ± assim.

ahhh agora deu pra entender melhor, mas no caso sao criados 2 objetos de instancia, c1 e c2 cada um deles possuem um objeto Short e um Long certo? entao eu coloco c1 = null entao tambem os objetos que foram criados juntos com a instancia de c1 tambem ficam disponiveis para o GC porque tambem recebem null? e o Short e Long que tambem foram criados assim que o c2 foi instaciado continuam com um valor porque o c2 ainda esta vivo?

ou entao funciona que assim que o primeiro objeto da classe eh instanciado junto com ele tambem eh criado os membros da classe, Long e Short? e no caso o c2 que foi o segundo instanciado nao cria o Long e o Short pois ja foram instaciados com o c1 entao se o c2 receber null somente ele vai ser disponivel para o GC, mas se o c1 que foi instanciado primeiro receber null assim com ele o Short e o Long tambem fcam disponiveis?

to meio confuso a respeito disso.

Jeferson_Manetti

gumatias:
rafaelsantos1983:
hehee num é besteira não… também apanhei nesa questão quando estava estudando GC.

Mas pelo o que estudei, quando um objeto fica disponível para o GC, os seus membros(atributos) que são objetos também ficam disponíveis.
Não sei falar técnicamente esse assunto, mas a explicação é ± assim.

ahhh agora deu pra entender melhor, mas no caso sao criados 2 objetos de instancia, c1 e c2 cada um deles possuem um objeto Short e um Long certo? entao eu coloco c1 = null entao tambem os objetos que foram criados juntos com a instancia de c1 tambem ficam disponiveis para o GC porque tambem recebem null? e o Short e Long que tambem foram criados assim que o c2 foi instaciado continuam com um valor porque o c2 ainda esta vivo?

ou entao funciona que assim que o primeiro objeto da classe eh instanciado junto com ele tambem eh criado os membros da classe, Long e Short? e no caso o c2 que foi o segundo instanciado nao cria o Long e o Short pois ja foram instaciados com o c1 entao se o c2 receber null somente ele vai ser disponivel para o GC, mas se o c1 que foi instanciado primeiro receber null assim com ele o Short e o Long tambem fcam disponiveis?

to meio confuso a respeito disso.

nossa minha explicação deu oq falar… rss

tem uma coisa q vai facilitar a vida de vcs…
um Objeto só fica disponivel para o GC qnd nehum thread ativa consegue acessa-lo

oq acontece aqui…

//qnd faço isso
Dog c1 = new Dog();

// ele cria 3 obj... 1 Dog, 1 Integer e  1 Long... certo?
// dai fica o seguinte c1 aponta para o Dog este por sua vez tem duas referencias 
//uma q aponta pra um Integer e outra q aponta para um Long 
// então se eu fizer isto...

c1 = null;

// eu não vou ter mais uma referencia pra Dog... certo?
// nehum thread vai conseguir chegar ate Dog...
// se eu não tenho referencia pra Dog como eu vou conseguir alcançar meu Integer e meu Long?
// entenderam....
// o Integer e o Long continuam la bunitinho em algum lugar... mais nunca serão acessados...
//por isso o Sr GC se encarrega disso..
// Blz

uma outra coisa pessoal… estou explicando dentro da tag . tem algum problema nisso?
visualização… algo assim?
se tiver me avisem…
blz t+

G

Nao cara, nao tem problema nenhum nao… entao eu entendi velho… mas digamos que temos, um Integer, e um Long…

ai instanciamos 2 objetos:

Dog c1 = new Dog();
Dog c2 = new Dog();

entao para chegar ateh o Integer e o Long temos dois caminhos certo? pelo c1 ou pelo c2… se eu der null no c1, c1 = null… entao isso significa que pelo c1 nao tem como eu chegar ao Integer e o Long, mas eu ainda consigo chegar neles pelo c2 certo? entao no caso o Integer e o Long nao estao disponiveis ainda pelo GC porque o c2 ainda continua referenciando para eles sendo assim ainda eh possivel que uma Thread chegue ateh eles, pelo c2… entao ai no caso somente 1 objeto vai ser disponivel para o GC no caso o c1???

rafaelsantos1983

gumatias,

Quando você faz:

Dog c1 = new Dog();

Você está instanciando 1 OBJETO Dog, ou seja a variável c1(que está na pilha) irá apontar para o objeto Dog(criado no HEAP). ok?
Com o objeto Dog(c1) criado, também é criado outros dois objeto, um Integer e um Long.
Para o objt Integer, existe um atributo na pilha que aponta para ele.
Para o objt Long, existe um atributo na pilha que aponta para ele.

Quando foi instância outro OBJETO Dog através de:
Quando você faz:

Dog c2 = new Dog();

Você está fazendo, instanciando 1 OBJETO Dog(Outro obj), ou seja a variável c2(que está na pilha) irá apontar para o objeto Dog(criado no HEAP, outro objeto criado no HEAP). ok?
Com o objeto Dog(c2) criado, também é criado outros dois objeto, um Integer e um Long. (Outros, que não tem nada haver com aqueles dois criados anteriormente por causa de c1) ok?
Para o objt Integer, existe um atributo na pilha que aponta para ele. (Outro objeto, não é o mesmo criado pelo c1) ok?
Para o objt Long, existe um atributo na pilha que aponta para ele. (Outro objeto, não é o mesmo criado pelo c1) ok?

Com isso você tem 6 objetos
2 Dgo’s
2 Integer’s
2 Long’s

ok?

Reumindo

c1 tem i1 e l1
c2 tem i2 e l2

ok?

Portanto quando você faz c1 = null, nenhuma thread conseguirá mas acessar ao objeto c1, e consequentemente também não poderá acessar aos atributos de c1, ou seja i1 e l1.
Esses dois atributos são dois objetos(um Integer e outro Long), com isso eles também serão removidos pelo GC, quando o GC for executado.

Por outro lado o objeto c2, continua lá tranquilo, vivendo feliz da vida, e consequentemente os seus atributos i2 e l2 também estão felizes da vida, por que podem ser acessados através de c2.

blz?

Não misture os objetos, i1 != i2 e l1 != l2, apesar de serem do mesmo tipo e terem o mesmo valor, não tem a mesma referência.

ok?

Espero ter ajudado. 8)

Jeferson_Manetti

gumatias:
Nao cara, nao tem problema nenhum nao… entao eu entendi velho… mas digamos que temos, um Integer, e um Long…

ai instanciamos 2 objetos:

Dog c1 = new Dog();
Dog c2 = new Dog();

entao para chegar ateh o Integer e o Long temos dois caminhos certo? pelo c1 ou pelo c2… se eu der null no c1, c1 = null… entao isso significa que pelo c1 nao tem como eu chegar ao Integer e o Long, mas eu ainda consigo chegar neles pelo c2 certo? entao no caso o Integer e o Long nao estao disponiveis ainda pelo GC porque o c2 ainda continua referenciando para eles sendo assim ainda eh possivel que uma Thread chegue ateh eles, pelo c2… entao ai no caso somente 1 objeto vai ser disponivel para o GC no caso o c1???

iaew blz?

bom vc esta confundindo os conceitos de variaves de instancia… com variaveis de classe…

cada vez q vc faz new Dog();
ele cria um novo obj dog com suas respectivas variaveis de referencia (Integer e Long).
cada obj tem a sua… isso simplismente pq são variaveis de instancia ^^
entedeu?

isso q vc falou ai acontece qnd vc tem variaveis static ou variaveis de classe
ai sim vc teria somente 1 Integer e 1 Long
pq eles compartilhariam a mesma variavel ^^
sacou?

talvez o exemplo com Integer e Long esteja confundindo um pouco…
vamos usar assim…

public class Dog{
// ah... coloquei default pra num fica criando get e set... afinal to fazendo an unha... rss
Colar colar; // aqui seria o Integer dos exemplos anteriores
Roupa roupinha; // aqui seria o Long dos exemplos anteriores

public Dog(){
   // aqui estou criando 2 objs... ta vendo?
   this.colar = new Colar(10); 
   this.roupinha = new Roupa("azul");
} 

public static void main(String[] gc){
   // aqui crio o Dog... junto com ele sera cirado um Colar e uma Roupa
   Dog dog = new Dog();
   // olha o q eu posso fazer com a variavel dog
   System.out.println("tamanho" + dog.colar.tamanho);
   System.out.println("Cor da Roupa" + dog.roupinha.cor);

   // agora olhe só...
   dog = null; // nesse momento ja era meu obj Dog, meu obj Roupa e meu obj Colar.

  // como eu vou saber o tamanho do colar? se eu não tenho nenhum cachoro!!!
  // isso aqui da erro de execução.... NullPointerException...
  System.out.println("tamanho" + dog.colar.tamanho);

 // minha thread main...
 // não consegui alcançar o Dog ( dog = null;)
 // tambem não consegue alcançar o Colar e a Roupa...
 // dog.colar... dog.roupinha... NullPointerException
 // por esse motivo o GC vai la e limpa td...
 // qnd ele faz isso? dog = null aqui?
 // pode ser ou não pode ser...
 // qnd faço isso dog =null... não siginifica q ele vai entra em açao...
 // significa apenas q o obj Dog esta apto para o GC... q pode ser executado ou não...
 // ele tem vontade propria... usahushausha
 // vc ate pode chama-lo com System.gc() ... eita e isso mesmo? num lembro =(
 // bom vc pode chama-lo... mais nd garante q ele vá executar imediatamente =)

 // então não confunda apto com foi coletado ^^
 
}

}

class Colar{

int tamanho;

public Colar(int i){
   this.tamanho = i;
}

}

class Roupa{

String cor;

public Roupa(String c){
   this.cor=c;
}

}

ficou mais claro agora?

G

ficou cara agora ja entendi, tinha feito uns exercicios ontem no papel e consegui entender bem mais do que antes, que tava sem nocao nenhuma.
valeu!

Criado 3 de fevereiro de 2009
Ultima resposta 5 de fev. de 2009
Respostas 21
Participantes 7