O espaço de memória consumido por um objeto com 100 atributos é igual ao de 100 objetos, com um atributo cada?
Quanta memória é alocada para um objeto?
Quanto espaço adicional é usado ao adicionar um atributo?
A Mindprod ressalta que essa não é uma pergunta direta a ser respondida:
Uma JVM é livre para armazenar dados da maneira que desejar internamente, grande ou pequeno endian, com qualquer quantidade de preenchimento ou sobrecarga, embora os primitivos devam se comportar como se tivessem os tamanhos oficiais.
Por exemplo, a JVM ou o compilador nativo pode decidir armazenar umboolean[]
em pedaços longos de 64 bits como umBitSet
. Não precisa lhe dizer, desde que o programa dê as mesmas respostas.
- Pode alocar alguns objetos temporários na pilha.
- Pode otimizar algumas variáveis ou chamadas de método totalmente inexistentes, substituindo-as por constantes.
- Pode versão de métodos ou loops, ou seja, compilar duas versões de um método, cada uma otimizada para uma determinada situação, e então decidir antecipadamente qual chamar.
É claro que o hardware e o sistema operacional têm caches multicamadas, no cache de chips, no cache SRAM, no cache DRAM, no conjunto de trabalho comum da RAM e no armazenamento de backup em disco. Seus dados podem ser duplicados em todos os níveis de cache. Toda essa complexidade significa que você pode prever apenas aproximadamente o consumo de RAM.
Você pode usar Instrumentation.getObjectSize()
para obter uma estimativa do armazenamento consumido por um objeto.
Para visualizar o layout, a área de cobertura e as referências reais do objeto, você pode usar a ferramenta JOL (Java Object Layout) .
Em um JDK moderno de 64 bits, um objeto possui um cabeçalho de 12 bytes, preenchido com um múltiplo de 8 bytes; portanto, o tamanho mínimo do objeto é 16 bytes. Para JVMs de 32 bits, a sobrecarga é de 8 bytes, preenchida com um múltiplo de 4 bytes. (Da resposta de Dmitry Spikhalskiy , a resposta de Jayen e JavaWorld .)
Normalmente, as referências são de 4 bytes em plataformas de 32 bits ou em plataformas de 64 bits até -Xmx32G
; e 8 bytes acima de 32Gb ( -Xmx32G
). (Consulte as referências de objetos compactados .)
Como resultado, uma JVM de 64 bits normalmente exigiria de 30 a 50% mais espaço de heap. ( Devo usar uma JVM de 32 ou 64 bits?, 2012, JDK 1.7)
Os wrappers in a box têm sobrecarga em comparação com os tipos primitivos (do JavaWorld ):
Integer
: O resultado de 16 bytes é um pouco pior do que eu esperava, porque umint
valor pode caber em apenas 4 bytes extras. Usar umInteger
custo me custa uma sobrecarga de memória de 300% em comparação com quando posso armazenar o valor como um tipo primitivo
Long
: 16 bytes também: Claramente, o tamanho real do objeto no heap está sujeito ao alinhamento de memória de baixo nível feito por uma implementação JVM específica para um tipo de CPU específico. Parece que aLong
é 8 bytes de sobrecarga de objeto, mais 8 bytes a mais para o valor longo real. Por outro lado,Integer
tinha um orifício de 4 bytes não utilizado, provavelmente porque a JVM I utiliza forças no alinhamento de objetos em um limite de palavras de 8 bytes.
Outros contêineres também são caros:
Matrizes multidimensionais : oferece outra surpresa.
Os desenvolvedores geralmente empregam construções comoint[dim1][dim2]
na computação numérica e científica.Em uma
int[dim1][dim2]
instância de matriz, todaint[dim2]
matriz aninhada é umaObject
por si só. Cada um deles adiciona a sobrecarga usual da matriz de 16 bytes. Quando não preciso de uma matriz triangular ou irregular, isso representa uma sobrecarga pura. O impacto aumenta quando as dimensões da matriz diferem bastante.Por exemplo, uma
int[128][2]
instância ocupa 3.600 bytes. Comparado aos 1.040 bytes que umaint[256]
instância usa (que tem a mesma capacidade), 3.600 bytes representam uma sobrecarga de 246%. No caso extremo debyte[256][1]
, o fator de sobrecarga é quase 19! Compare isso com a situação C / C ++ na qual a mesma sintaxe não adiciona sobrecarga de armazenamento.
String
:String
o crescimento da memória de a controla o crescimento de sua matriz de caracteres interna. No entanto, aString
classe adiciona outros 24 bytes de sobrecarga.Para um não vazio
String
de tamanho 10 caracteres ou menos, o custo adicional adicionado em relação à carga útil (2 bytes para cada caractere mais 4 bytes para o comprimento) varia de 100 a 400 por cento.
Considere este objeto de exemplo :
class X { // 8 bytes for reference to the class definition
int a; // 4 bytes
byte b; // 1 byte
Integer c = new Integer(); // 4 bytes for a reference
}
Uma soma ingênua sugeriria que uma instância de X
usaria 17 bytes. No entanto, devido ao alinhamento (também chamado de preenchimento), a JVM aloca a memória em múltiplos de 8 bytes, portanto, em vez de 17 bytes, alocaria 24 bytes.
Depende da arquitetura / jdk. Para uma arquitetura moderna de JDK e 64 bits, um objeto possui um cabeçalho de 12 bytes e um preenchimento de 8 bytes - portanto, o tamanho mínimo do objeto é 16 bytes. Você pode usar uma ferramenta chamada Java Object Layout para determinar um tamanho e obter detalhes sobre o layout do objeto e a estrutura interna de qualquer entidade ou adivinhar essas informações por referência de classe. Exemplo de uma saída para Inteiro no meu ambiente:
Portanto, para Inteiro, o tamanho da instância é de 16 bytes, porque 4 bytes int compactados no local logo após o cabeçalho e antes do limite do preenchimento.
Exemplo de código:
Se você usa o maven, para obter o JOL:
fonte
Cada objeto possui uma certa sobrecarga para as informações de tipo e monitor associadas, bem como os próprios campos. Além disso, os campos podem ser definidos praticamente da maneira que a JVM achar melhor (eu acredito) - mas, como mostrado em outra resposta , pelo menos algumas JVMs serão compactadas com bastante rigidez. Considere uma classe como esta:
vs
Em uma JVM de 32 bits, eu esperaria 100 instâncias de
SingleByte
ocupassem 1200 bytes (8 bytes de sobrecarga + 4 bytes para o campo devido ao preenchimento / alinhamento). Eu esperaria que uma instânciaOneHundredBytes
levasse 108 bytes - a sobrecarga e, em seguida, 100 bytes, compactados. Certamente, pode variar de acordo com a JVM - uma implementação pode decidir não compactar os campos emOneHundredBytes
, levando a 408 bytes (= sobrecarga de 8 bytes + 4 * 100 bytes alinhados / preenchidos). Em uma JVM de 64 bits, a sobrecarga também pode ser maior (não tenho certeza).EDIT: Veja o comentário abaixo; aparentemente o HotSpot preenche os limites de 8 bytes em vez de 32, portanto, cada instância de
SingleByte
leva 16 bytes.De qualquer maneira, o "único objeto grande" será pelo menos tão eficiente quanto vários objetos pequenos - para casos simples como esse.
fonte
A memória total utilizada / livre de um programa pode ser obtida no programa via
O tempo de execução possui vários métodos relacionados à memória. O exemplo de codificação a seguir demonstra seu uso.
fonte
Parece que todo objeto possui uma sobrecarga de 16 bytes em sistemas de 32 bits (e 24 bytes em sistemas de 64 bits).
http://algs4.cs.princeton.edu/14analysis/ é uma boa fonte de informação. Um exemplo entre muitos bons é o seguinte.
http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf também é muito informativo, por exemplo:
fonte
Não.
fonte
Não, o registro de um objeto também requer um pouco de memória. 100 objetos com um atributo ocupam mais memória.
fonte
A questão será muito ampla.
Depende da variável de classe ou você pode chamar como estados o uso de memória em java.
Ele também possui alguns requisitos adicionais de memória para cabeçalhos e referências.
A memória heap usada por um objeto Java inclui
memória para campos primitivos, de acordo com seu tamanho (veja abaixo os tamanhos dos tipos primitivos);
memória para campos de referência (4 bytes cada);
um cabeçalho de objeto, consistindo em alguns bytes de informações de "limpeza";
Os objetos em java também requerem algumas informações de "limpeza", como gravar a classe, ID e sinalizadores de status de um objeto, como se o objeto está atualmente acessível, bloqueado pela sincronização, etc.
O tamanho do cabeçalho do objeto Java varia nas jvm de 32 e 64 bits.
Embora estes sejam os principais consumidores de memória, o jvm também requer campos adicionais, algumas vezes como no alinhamento do código, etc.
Tamanhos de tipos primitivos
booleano e byte - 1
char & short - 2
int & float - 4
longa e dupla - 8
fonte
Obtive resultados muito bons com a abordagem java.lang.instrument.Instrumentation mencionada em outra resposta. Para obter bons exemplos de seu uso, consulte a entrada Contador de Memória de Instrumentação no Boletim de Notícias do JavaSpecialists e a biblioteca java.sizeOf no SourceForge.
fonte
Caso seja útil para qualquer pessoa, você pode baixar do meu site um pequeno agente Java para consultar o uso de memória de um objeto . Isso permitirá que você consulte também o uso de memória "profunda".
fonte
(String, Integer)
Guava Cache usa por elemento. Obrigado!não, 100 objetos pequenos precisam de mais informações (memória) que um grande.
fonte
As regras sobre quanta memória é consumida dependem da implementação da JVM e da arquitetura da CPU (32 bits versus 64 bits, por exemplo).
Para as regras detalhadas da JVM SUN, consulte meu blog antigo
Atenciosamente, Markus
fonte