Etapas do processo de alocação de memória para objetos Java
Pergunta
O que acontece na memória quando uma classe instancia o objeto a seguir?
public class SomeObject{
private String strSomeProperty;
public SomeObject(String strSomeProperty){
this.strSomeProperty = strSomeProperty;
}
public void setSomeProperty(String strSomeProperty){
this.strSomeProperty = strSomeProperty;
}
public String getSomeProperty(){
return this.strSomeProperty;
}
}
Na classe de SomeClass1
:
SomeObject so1 = new SomeObject("some property value");
Na classe de SomeClass2
:
SomeObject so2 = new SomeObject("another property value");
Como é a memória alocada para o objeto recentemente instanciado e suas propriedades?
Solução
Vamos passar por isso:
SomeObject so1 = new SomeObject("some property value");
... na verdade, é mais complicado do que parece, porque você está criando uma nova string. Pode ser mais fácil pensar como:
String tmp = new String("some property value");
SomeObject so1 = new SomeObject(tmp);
// Not that you would normally write it in this way.
(Para ser absolutamente preciso - estes não são realmente equivalentes. No original, a 'nova string' é criada no horário de compilação e faz parte da imagem .classe. Você pode pensar nisso como um hacker de desempenho.)
Então, primeiro a JVM aloca espaço para a corda. Você normalmente não sabe ou se importa com os internos da implementação da string; portanto, basta confiar que um pedaço de memória está sendo usado para representar "algum valor da propriedade". Além disso, você tem alguma memória alocada temporariamente contendo uma referência à string. Na segunda forma, é explicitamente chamado tmp
; Na sua forma original, Java lida com isso sem nomeá -lo.
Em seguida, a JVM aloca espaço para um novo objeto. Isso é um pouco de espaço para a contabilidade interna de Java e o espaço para cada um dos campos do objeto. Nesse caso, há apenas um campo, strSomeProperty
.
Ter em mente que strSomeProperty
é apenas uma referência a uma string. Por enquanto, será inicializado para NULL.
Em seguida, o construtor é executado.
this.strSomeProperty = strSomeProperty;
Tudo isso faz é copiar o referência para a corda, em seu strSomeProperty
campo.
Finalmente, o espaço é alocado para a referência do objeto so1
. Isso é definido com uma referência ao objeto.
so2
Funciona exatamente da mesma maneira.
Outras dicas
Determinando o uso da memória em Java pelo Dr. Heinz M. Kabutz fornece uma resposta precisa, além de um programa para calcular o uso da memória. A parte relevante:
- A aula ocupa pelo menos 8 bytes. Então, se você diz novo objeto (); Você alocará 8 bytes na pilha.
- Cada membro de dados ocupa 4 bytes, exceto por longa e dupla, que ocupam 8 bytes. Mesmo que o membro de dados seja um byte, ele ainda ocupará 4 bytes! Além disso, a quantidade de memória usada é aumentada em 8 blocos de bytes. Portanto, se você tiver uma classe que contém um byte, ele ocupará 8 bytes para a classe e 8 bytes para os dados, totalizando 16 bytes (gemidos!).
- Matrizes são um pouco mais inteligentes. Os primitivos ficam embalados em matrizes; portanto, se você tiver uma variedade de bytes, cada um deles assumirá um byte (uau!). O uso da memória, é claro, ainda sobe em 8 blocos de bytes.
Como as pessoas apontaram nos comentários, as cordas são um caso especial, porque podem ser internadas. Você pode raciocinar sobre o espaço que eles ocupam da mesma maneira, mas lembre -se de que o que parece várias cópias da mesma string pode realmente apontar para a mesma referência.
Pontos a lembrar:
- Quando um método é chamado, um quadro é criado no topo da pilha.
- Uma vez que o método foi concluído sua execução, fluxo de controle retorna para o método de chamada e sua correspondente estrutura de pilha é liberado.
- Variáveis locais são criadas na pilha.
- Variáveis de instância são criadas na pilha e são parte do objeto a que pertencem.
- Variáveis de referência são criadas na pilha.