Java é um tipo de linguagem de coleta de lixo. Sua vantagem é que os desenvolvedores não precisam gerenciar deliberadamente a alocação de memória, o que reduz a possibilidade de os aplicativos travarem devido a falhas de segmentação local e impedem que a memória descongeladora aperte a pilha (heap). Portanto, o código escrito é mais seguro.
Infelizmente, ainda existem muitos vazamentos lógicos em Java que são propensos a vazamentos de memória. Se você não tomar cuidado, seu aplicativo Android pode desperdiçar facilmente a memória não-frequente, o que eventualmente levará a um erro de erro de memória que está se esgotando (fora da memória, OOM).
1. O motivo do vazamento geral da memória é que, quando todas as referências ao objeto foram liberadas, o objeto não foi liberado. (Nota do tradutor: o cursor esqueceu de fechar, etc.)
2. O motivo do vazamento de memória lógica é que, quando o aplicativo não precisa mais desse objeto, todas as referências ao objeto não foram liberadas.
Se você possui uma forte referência a um objeto, o coletor de lixo não poderá reciclar o objeto na memória.
No desenvolvimento do Android, o problema de vazamento de memória mais provável é o contexto. Por exemplo, o contexto da atividade contém um grande número de referências de memória, como hierarquias de exibição e outros recursos. Uma vez vazado um contexto, também significa vazar todos os objetos para os quais aponta. As máquinas Android têm memória limitada e muitos vazamentos de memória podem facilmente levar ao OOM.
Detectar vazamentos de memória lógica requer julgamento subjetivo, especialmente o ciclo de vida do objeto não está claro. Felizmente, a atividade tem um ciclo de vida claro e é fácil encontrar a causa do vazamento. Atividade.ondestroy () é considerado o fim da vida da atividade. Programaticamente, ele deve ser destruído, ou o sistema Android precisa reciclar essa memória (nota do tradutor: quando a memória for insuficiente, o Android reciclará atividades invisíveis).
Se esse método for executado, ainda há uma forte referência à atividade na pilha, e o coletor de lixo não pode marcá -lo como memória reciclada, e nosso objetivo original é reciclá -lo!
O resultado é que a atividade sobrevive fora de seu ciclo de vida.
A atividade é um objeto de peso pesado e deve ser tratado pelo sistema Android. No entanto, os vazamentos de memória lógica sempre acontecem inadvertidamente. (Nota do tradutor: uma vez tentei uma atividade que causou um vazamento de memória de 20m). No Android, existem apenas duas armadilhas que levam a possíveis vazamentos de memória:
A variável estática do processo global (Process-global). Esse monstro que ignora o estado da aplicação e mantém uma forte referência à atividade.
Tópicos que vivem fora do ciclo de vida da atividade. Nenhuma referência forte à atividade foi limpa.
Verifique se você encontrou as seguintes situações.
1. ATIVIDADES ESTÁTICAS
A variável de atividade estática é definida na classe e a instância de atividade atualmente em execução é atribuída a essa variável estática.
Se essa variável estática não for liberada após o final do ciclo de vida da atividade, ela causará um vazamento de memória. Como as variáveis estáticas passam pelo ciclo de vida deste aplicativo, as atividades vazadas sempre existirão no processo de aplicação e não serão coletadas pelo coletor de lixo.
atividade estática atividade; Void setStaticActivity () {Atividade = this;} View Sabutton = FindViewById (r.id.sa_button); sabutton.setOnClickListener (new View.OnClickListener () {@Override public void OnClick (View V) {Setsticticity (); Nextativity;2. Visualizações estáticas
Situações semelhantes podem acontecer no modo Singleton e, se a atividade for frequentemente usada, é prático salvar uma instância na memória. Como mencionado anteriormente, forçar o ciclo de vida de uma atividade é bastante perigoso e desnecessário, e isso não pode ser feito de qualquer maneira.
Caso especial: se uma inicialização de visualização consome muitos recursos e permanecer inalterada durante um ciclo de vida da atividade, ela pode ser transformada em estática e carregada na Hierachy View. Dessa forma, quando a atividade é destruída, o recurso deve ser divulgado. (Nota do tradutor: a memória não é liberada no código de amostra. Apenas nulo esta visualização estática, mas ainda não é recomendável usar o método de visão estática)
visão estática; void setStaticView () {View = findViewById (r.id.sv_button);} View svbutton = findViewById (r.id.sv_button); svbutton.setOnClickListener (view.onClickListener () {@Override Public Void onClick (ViewSt) {Sett) {Sett) {Sett) {Sett);3. Classes
Continue, assumindo que há uma classe interna na atividade, isso pode melhorar a legibilidade e o encapsulamento. Se criarmos uma classe interna e realizarmos uma referência a uma variável estática, parabéns, o vazamento de memória não está longe de você (Nota do tradutor: vazio quando destruído, hum).
objeto estático privado interno; void CreateInnerClass () {class InnerClass {} interno = new InnerClass ();} Ver icbutton = findViewById (r.id.ic_button); icbutton.setOnClickListener (view.oNClickListener () {s @Override Public Void OnClick (View VrayClick) {View) {CreateN;Uma das vantagens das classes internas é que elas podem acessar classes externas. Infelizmente, o motivo dos vazamentos de memória é que as classes internas mantêm fortes referências a instâncias de classe externas.
4. Classes anônimas
Da mesma forma, as aulas anônimas também mantêm referências a classes externas. Portanto, os vazamentos de memória são fáceis de acontecer quando você define o assíncrono anônimo em sua atividade. Quando a tarefa assíncrona executa uma tarefa demorada em segundo plano, a atividade é infelizmente destruída (Nota do tradutor: saídas do usuário, reciclagem do sistema), esta instância de atividade realizada pela assíncada não será reciclada pelo coletor de lixo até que a tarefa assíncrona seja concluída.
void startasyncTask () {novo assyncTask <void, void, void> () {@Override Protected void Doinbackground (void ... params) {while (true); }. startasyncTask ();5.Handler
Da mesma forma, defina o Anonymous Runnable e execute -o com o manipulador de classe anônimo. A classe interna executável reterá uma referência implícita à classe externa e é passada para a messageQueue da fila de mensagens do manipulador. A instância da atividade não será destruída até que a mensagem da mensagem seja processada, resultando em um vazamento de memória.
void createHandler () {new Handler () {@Override public void handleMessage (mensagem de mensagem) {super.handleMessage (mensagem); }} .PostDelayed (new Runnable () {@Override public void run () {while (true);}}, long.max_value >> 1);} visualize hbutton = findviewId (r.id.h_button); hbutton.setOnClickLlistner (view.onCllin.OnClin {CreateHandler ();6.Threads
Mais uma vez, mostramos vazamentos de memória através do thread e TimerTask.
void spawnThread () {new Thread () {@Override public void run () {while (true); }.7.TimerTask
Desde que seja uma instância de uma classe anônima, independentemente de estar no thread do trabalhador ou não, ele manterá uma referência à atividade, resultando em um vazamento de memória.
void scheduleTimer () {new Timer (). cronograma (new TimerTask () {@Override public void run () {while (true);}}, long.max_value >> 1);} view ttbutton = findviewbyid (r.id.tt_button); ttbutton.setOnTon (r.id.tt_button);} ttbutton.setOnTon (r.id.tt_button); ttbutton.seton (r.id.tt_button);} ttbutton.seton (r.id.tt_button); ttbutton.setOnCliNDON (r.id.tt_button); Void OnClick (View V) {ScheduletImer ();8. Gerente do Sensor
Finalmente, os serviços do sistema podem ser obtidos através do context.GetSystemService (Int Name). Esses serviços funcionam em seus respectivos processos, ajudando os aplicativos a lidar com tarefas em segundo plano e interações de hardware. Se você precisar usar esses serviços, pode registrar os ouvintes, o que fará com que o serviço mantenha uma referência ao contexto. Se esses ouvintes não forem registrados quando a atividade for destruída, ela causará vazamentos de memória.
void RegisterListener () {Sensormanager sensorManager = (sensorManager) getSystemService (sensor_service); Sensor sensor = sensorManager.getDefaultSensor (sensor.type_all); sensorManager.RegisterListener (this, sensor, Sensormanager.sensor_delay_fastest);} Visualize srbutton = findViewById (r.id.sm_button); smbutton.setOnClickListener (viewLicklicklistener () {@Override Public anroid onClick onClick (LIGHT);Resumir
Tendo visto tantos exemplos que podem levar a vazamentos de memória, é fácil comer toda a memória do seu telefone, fazendo coleta de lixo e processando com mais frequência e, mesmo na pior das hipóteses, isso levará à OOM. As operações de coleta de lixo são caras e podem levar a atrasos visíveis. Portanto, preste atenção à cadeia de referência mantida ao instantador e geralmente realize verificações de vazamentos de memória.