Olá! Acho que você não ficará muito surpreso se dissermos que o tamanho da memória do seu computador é limitado :) Até mesmo um disco rígido, que é muitas vezes maior que a RAM, pode ser preenchido com seus jogos favoritos, séries de TV, e assim por diante. Para evitar que isso aconteça, você precisa monitorar o estado atual da memória e excluir arquivos desnecessários do seu computador. O que a programação Java tem a ver com tudo isso? Direto! Afinal, quando qualquer objeto é criado pela máquina Java, é alocada memória para ele. Em um programa realmente grande, dezenas e centenas de milhares de objetos são criados, cada um com sua própria memória alocada. Mas há quanto tempo você acha que todos esses objetos existem? Eles “vivem” durante todo o tempo em que nosso programa está em execução? Claro que não. Com todas as vantagens dos objetos Java, eles não são imortais :) Os objetos têm seu próprio ciclo de vida. Hoje faremos uma pequena pausa na escrita de código e veremos esse processo :) Além disso, é muito importante para entender o funcionamento do programa e gerenciar recursos. Então, onde começa a vida de um objeto? Como uma pessoa - desde o seu nascimento, isto é, a criação.
O coletor de lixo é um mecanismo interno do Java responsável por liberar memória, ou seja, remover dela objetos desnecessários. Não foi à toa que escolhemos uma imagem com um aspirador robô para retratá-lo. Afinal, o coletor de lixo funciona quase da mesma maneira: em segundo plano, ele “viaja” pelo seu programa, coleta o lixo e ao mesmo tempo você praticamente não interage com ele. Sua função é remover objetos que não são mais utilizados no programa. Assim, libera memória do computador para outros objetos. Você se lembra que no início da palestra falamos que na vida cotidiana é preciso monitorar o estado do seu computador e deletar arquivos antigos? Portanto, no caso de objetos Java, o coletor de lixo faz isso para você. O Garbage Collector é iniciado várias vezes durante a operação do seu programa: ele não precisa ser chamado especificamente e receber comandos, embora isso seja tecnicamente possível. Posteriormente falaremos mais sobre ele e analisaremos mais detalhadamente o processo de seu trabalho. No momento em que o coletor de lixo chega ao objeto, pouco antes de sua destruição, um método especial é chamado no objeto -
Para que funcione bem, é preciso manter o piso em bom estado e retirar de lá tudo que o aspirador não aguenta. O coletor de lixo funciona com o mesmo princípio. Se sobrarem muitos objetos no programa que ele não consegue coletar (como uma meia ou Lego para um aspirador de pó robô), a certa altura a memória acabará. E não apenas o programa que você escreveu irá congelar, mas também todos os outros programas em execução no computador naquele momento. Também não haverá memória suficiente para eles. É assim que se parecem o ciclo de vida do objeto e o coletor de lixo em Java. Não há necessidade de memorizar isso: basta entender o princípio de funcionamento. Na próxima palestra falaremos mais detalhadamente sobre esses processos, mas por enquanto você pode voltar a resolver problemas do JavaRush :) Boa sorte!
Cat cat = new Cat();//вот сейчас и начался vital цикл нашего an object Cat!
Primeiro, a Java Virtual Machine aloca a quantidade necessária de memória para criar o objeto. Então ela cria um link para ele, no nosso caso - cat
para poder rastreá-lo. Depois disso, todas as variáveis são inicializadas, o construtor é chamado e eis que nosso novo objeto já está vivendo sua própria vida :) A vida útil dos objetos é diferente, não há números exatos aqui. Em qualquer caso, durante algum tempo ele vive dentro do programa e desempenha suas funções. Para ser mais preciso, um objeto está “vivo” enquanto houver referências a ele. Assim que não houver mais links, o objeto “morre”. Por exemplo:
public class Car {
String model;
public Car(String model) {
this.model = model;
}
public static void main(String[] args) {
Car lamborghini = new Car("Lamborghini Diablo");
lamborghini = null;
}
}
No método, main()
o objeto carro Lamborghini Diablo deixa de estar vivo já na segunda linha. Havia apenas um link para ele e agora esse link foi atribuído null
. Como não há mais referências ao Lamborghini Diablo, ele vira “lixo”. Não é necessário redefinir o link:
public class Car {
String model;
public Car(String model) {
this.model = model;
}
public static void main(String[] args) {
Car lamborghini = new Car("Lamborghini Diablo");
Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
lamborghini = lamborghiniGallardo;
}
}
Aqui criamos um segundo objeto, após o qual pegamos a referência lamborghini
e a atribuímos a este novo objeto. Existem agora Lamborghini Gallardo
duas referências ao objeto, mas Lamborghini Diablo
nenhuma ao objeto. Portanto o objeto Diablo
se torna lixo. E neste momento, o mecanismo Java embutido chamado coletor de lixo, ou em outras palavras - Garbage Collector, GC, entra em operação.
finalize()
. Pode ser usado para liberar alguns recursos adicionais que o objeto estava usando. O método finalize()
pertence à classe Object
. Ou seja, junto com equals()
, hashCode()
e toString()
, que você já conheceu anteriormente, qualquer objeto o possui. Sua diferença em relação a outros métodos é que ele é... como dizer... muito caprichoso. Ou seja, nem sempre é chamado antes de destruir um objeto. Programar é uma coisa precisa. O programador diz ao computador para fazer alguma coisa, e o computador faz. Você provavelmente já está acostumado com esse comportamento e pode ser difícil aceitar a ideia no início: “Antes que os objetos sejam destruídos, o método da finalize()
classe é chamado Object
. Ou não é chamado. Se tivermos sorte!" No entanto, isso é verdade. A própria máquina Java determina se deve chamar o método finalize()
em cada caso específico ou não. Por exemplo, vamos tentar executar o seguinte código para fins de experiência:
public class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
public Cat() {
}
public static void main(String[] args) throws Throwable {
for (int i = 0 ; i < 1000000; i++) {
Cat cat = new Cat();
cat = null;//вот здесь первый an object становится доступен сборщику мусора
}
}
@Override
protected void finalize() throws Throwable {
System.out.println("Объект Cat уничтожен!");
}
}
Criamos um objeto Cat
e na próxima linha de código redefinimos a única referência a ele. E assim - um milhão de vezes. Substituímos explicitamente o método finalize()
e ele deve imprimir a string no console um milhão de vezes, sempre antes de destruir o objeto Cat
. Mas não! Para ser mais preciso, ele funcionou apenas 37.346 vezes no meu computador! Ou seja, apenas em 1 dos 27 casos a máquina Java que instalei decidiu chamar um método finalize()
- em outros casos, a coleta de lixo prosseguiu sem isso. Tente executar este código você mesmo: provavelmente o resultado será diferente. Como você pode ver, finalize()
é difícil chamá-lo de parceiro confiável :) Portanto, um pequeno conselho para o futuro: você não deve confiar no método finalize()
no caso de liberar alguns recursos críticos. Talvez a JVM ligue, talvez não. Quem sabe? Se durante seu tempo de vida seu objeto ocupou alguns recursos que foram super importantes para performance, por exemplo, manteve uma conexão aberta com o banco de dados, é melhor criar um método especial em sua classe para liberá-los e chamá-lo explicitamente quando o objeto for não é mais necessário. Desta forma você terá certeza de que o desempenho do seu programa não será prejudicado. No início dissemos que o gerenciamento de memória e a remoção de lixo são muito importantes, e isso é verdade. O manuseio inadequado de recursos e a falta de compreensão do processo de montagem de objetos desnecessários podem levar a vazamentos de memória. Este é um dos erros de programação mais famosos. O código escrito incorretamente pelo programador pode resultar na alocação de nova memória a cada vez para objetos recém-criados, enquanto objetos antigos e desnecessários não ficam disponíveis para remoção pelo coletor de lixo. Já que fizemos uma analogia com um aspirador robô, imagine o que aconteceria se, antes de ligar o robô, você espalhasse meias pela casa, quebrasse um vaso de vidro e deixasse um conjunto de Lego desmontado no chão. O robô, é claro, tentará fazer alguma coisa, mas em determinado momento ficará preso.
GO TO FULL VERSION