41 votes

Qu'est-ce qui détermine la taille des objets Java ?

Qu'est-ce qui contribue à la taille d'un objet unique en mémoire ?

Je sais que les primitives et les références le feraient, mais y a-t-il autre chose ? Le nombre de méthodes et leur longueur sont-ils importants ?

65voto

templatetypedef Points 129554

Ce qui est totalement dépendant de l'implémentation, mais il ya quelques facteurs qui influent sur la taille de l'objet en Java.

Tout d'abord, le nombre et les types des champs dans l'objet Java certainement influencer l'utilisation de l'espace, puisque vous devez avoir au moins autant d'espace de stockage que nécessaire pour contenir tous les champs de l'objet. Toutefois, en raison de rembourrage, l'alignement, et le pointeur de la compression des optimisations, il n'y a pas de formule directe vous pouvez utiliser pour calculer précisément la quantité d'espace utilisé de cette façon.

Comme pour les méthodes, généralement parlant, le nombre de méthodes d'un objet n'a pas d'impact sur sa taille. Les méthodes sont souvent mises en œuvre à l'aide d'une fonction appelée fonction virtuelle tables (ou "vtables"), il est possible d'invoquer des méthodes au moyen d'une base de référence de classe en temps constant. Ces tableaux sont généralement stockées par le fait d'avoir une seule instance de la vtable partagé entre plusieurs objets, puis d'avoir chaque magasin d'objets d'un seul pointeur vers la vtable.

Les méthodes d'Interface de compliquer ce tableau un peu, car il existe différentes implémentations possibles. Une application ajoute une nouvelle vtable pointeur pour chaque interface, de sorte que le nombre d'interfaces mises en œuvre peuvent affecter la taille de l'objet, tandis que d'autres ne le font pas. Encore une fois, c'est la mise en œuvre dépendant de la façon dont les choses sont réellement mis en mémoire, de sorte que vous ne pouvez pas savoir si oui ou non cela aura un coût mémoire.

Au meilleur de ma connaissance, il n'existe pas d'implémentations de la JVM en existence aujourd'hui, dans lequel la longueur d'une méthode d'influence sur la taille d'un objet. En général, un seul exemplaire de chaque méthode est stocké dans la mémoire, et le code est ensuite partagé entre toutes les instances d'un objet particulier. Avoir plus de méthodes peut exiger plus total de la mémoire, mais ne devrait pas influer sur le tarif de l'objet de mémoire pour les instances d'une classe. Cela dit, la JVM spec fait pas de promesses que ce doit être le cas, mais je ne peux pas penser à une mise en œuvre raisonnable qui permettrait de dépenser de l'espace supplémentaire par objet pour le code de la méthode.

En plus de champs et de méthodes, de nombreux autres facteurs pourraient contribuer à la taille d'un objet. Voici quelques-uns:

En fonction du type de garbage collector (ou collectionneurs) que la JVM est en utilisant, chaque objet peut avoir plus d'espace de rangement pour contenir des informations sur le fait que l'objet est vivants, morts, accessible, etc. Cela peut augmenter l'espace de stockage, mais il est hors de votre contrôle. Dans certains cas, la JVM peut optimiser objet de la taille d'essayer de stockage de l'objet sur la pile au lieu du tas. Dans ce cas, les frais généraux peuvent même ne pas être présent pour certains types d'objets.

Si vous utilisez la synchronisation, l'objet pourrait avoir de l'espace supplémentaire alloué pour elle, et donc qu'il peut être synchronisé sur. Certaines implémentations de la JVM ne pas créer un moniteur pour un objet jusqu'à ce qu'il est nécessaire, de sorte que vous pouvez finir par avoir de petits objets si vous n'utilisez pas de synchronisation, mais vous ne pouvez pas garantir que ce sera le cas.

En outre, pour aider les opérateurs comme instanceof et typecasting, chaque objet peut avoir un espace réservé pour contenir des informations de type. Généralement, elle est fournie avec l'objet de la vtable, mais il n'y a aucune garantie que ce sera vrai.

Si vous utilisez des affirmations, certains JVM implémentations de créer un champ dans votre classe qui contient ou non des affirmations sont activés. C'est alors utilisé pour activer ou désactiver les assertions au moment de l'exécution. Encore une fois, c'est spécifique à l'implémentation, mais il est bon de garder à l'esprit.

Si votre classe est un non statiques intérieur de la classe, il peut être nécessaire de maintenir une référence à la classe qui le contient, de sorte qu'il puisse accéder à ses champs. Cependant, la JVM peut optimiser cette distance si vous n'avez jamais de fin à l'aide de ce.

Si vous utilisez un anonyme intérieur de la classe, la classe peut-être besoin d'avoir de l'espace supplémentaire réservé à tenir l' final variables qui sont visibles dans son cadre englobant de sorte qu'ils peuvent être référencés à l'intérieur de la classe. C'est spécifique à l'implémentation de savoir si cette information est copiée dans le champs de la classe ou simplement stockés localement sur la pile, mais il peut augmenter la taille de l'objet.

Certaines implémentations de Object.hashCode() ou System.identityHashCode(Object) peut exiger des informations supplémentaires à être stockées dans chaque objet qui contient la valeur de code de hachage si elle ne peut pas calculer d'une autre manière (par exemple, si l'objet peut être déplacé dans la mémoire). Cela peut augmenter la taille de chaque objet.

Espérons que cette aide!

7voto

Stephen C Points 255558

Pour ajouter un peu de données (certes vagues) à l'excellente réponse de @templatetypedef. Ces chiffres sont pour des JVM 32 bits récentes typiques, mais ils sont spécifique à la mise en œuvre :

  • L'en-tête de chaque objet généralement 2 mots pour un objet ordinaire et 3 mots pour un tableau. L'en-tête comprend des drapeaux liés à la GC, et une sorte de pointeur vers la classe réelle de l'objet. Pour un tableau, un mot supplémentaire est nécessaire pour contenir la taille du tableau.

  • Si vous avez appelé (directement ou indirectement) System.identityHashCode() sur un objet, et qu'il a survécu à un cycle GC, alors ajoutez un mot supplémentaire pour stocker la valeur du hashcode. (Les JVM modernes utilisent une astuce astucieuse pour éviter de réserver un champ d'en-tête hashcode pour les objets de type tous objets ...)

  • La granularité de l'allocation de stockage peut être un multiple de mots ; par exemple 2.

  • Les champs d'un objet sont généralement alignés sur les mots, c'est-à-dire qu'ils ne sont pas emballés.

  • Les éléments d'un tableau d'un type primitif sont emballés, mais les booléens sont généralement représentés par un octet sous forme emballée.

  • Les références occupent 4 octets à la fois comme champs et comme éléments de tableau.

Les choses sont un peu plus compliquées pour les JVM 64 bits en raison de la compression des pointeurs (OOPS) dans certaines JVM. De plus, je ne suis pas sûr que les champs soient alignés sur 32 ou 64 bits.


(Note : les informations ci-dessus sont basées sur ce que j'ai entendu / lu à divers endroits de la part de diverses "personnes bien informées". Il n'y a pas de source définitive pour ce type d'information à part Oracle / Sun, et (AFAIK) ils n'ont rien publié).

4voto

johnnieb Points 394

Consultez java.sizeOf dans sourceforge ici : http://sizeof.sourceforge.net/

0voto

Clark Bao Points 1067

AFAIK, dans le code source de HBase, il y a une certaine caculation sur la taille de l'objet basée sur quelques règles communes connues comment les différents champs occupent les espaces. Et cela sera différent dans les OS 32bit ou 64bit. Au moins les personnes ci-dessus le savent toutes. Mais je n'ai pas cherché à savoir pourquoi ils font ça. Mais ils l'ont vraiment fait dans le code source.

En outre, la classe Java.lang.intrument.Intrumentation peut également le faire par getObjectSize(). Je suppose que le projet open source est également basé sur cette méthode. Dans ce lien, il y a des détails sur la façon de l'utiliser. En Java, quelle est la meilleure façon de déterminer la taille d'un objet ?

En guise de commentaire. En fait, je suis également intéressé par le fait que si vous le faites dans le code source, quel sera le cas d'utilisation le plus significatif ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X