52 votes

Quel est le coût en taille d'un héritage Java?

Il y a divers articles sur les interwebs qui tentent de l'estimation empirique de la surcharge d'un java.lang.Object , en particulier de la JVM des implémentations. Par exemple, j'ai vu la taille de la charge d'un nu Object estimé à 8 octets dans certains Jvm.

Ce que je voudrais savoir, c'est si typique de la JVM de la mise en œuvre de l' extends relation introduit incrémental taille généraux à tous les niveaux de la hiérarchie de classe. En d'autres termes, supposons que vous avez une hiérarchie de classe avec des niveaux de N de sous-classes. Est la surcharge de la représentation en mémoire d'une instance de classe O(1) O(N)?

J'imagine que c'est O(1) car, bien que la taille de certains caché moelleux de choses que vous devez être un Java Object (vtable, de la chaîne de classes) augmentera à mesure que la hiérarchie d'héritage grandit, ils poussent par la classe, et pas par exemple, et la JVM peut stocker constante de la taille des pointeurs vers ces entités dans une constante de la taille d'en-tête de chaque Object.

Donc, en théorie, les frais généraux directement attaché à la représentation en mémoire de tout objet Java doit être O(1) pour l'héritage de la profondeur N. personne Ne sait si c'est vrai dans la pratique?

23voto

Sotirios Delimanolis Points 77933

La spécification de la JVM unis

La Machine Virtuelle Java n'a pas de mandat particulier interne la structure des objets.

La spécification ne se soucie pas de la façon dont vous le faites. Mais...

Dans certains de Oracle implémentations de la Machine Virtuelle Java, un référence à une instance de classe est un pointeur sur une poignée qui est lui-même une paire de pointeurs: un tableau contenant les méthodes de la objet et un pointeur vers la Classe de l'objet qui représente le type de l'objet, et l'autre à la mémoire allouée dans le tas pour les données de l'objet.

Donc, dans le typique Oracle implémentations, il est O(1) pour les méthodes. Cette table de méthode est la Méthode de la Zone qui est par classe.

La Machine Virtuelle Java a une méthode de la zone qui est partagé entre tous La Machine Virtuelle Java threads. La méthode de la zone est analogue à la zone de stockage pour le code compilé d'un langage conventionnel ou analogue le "texte" d'un segment dans un processus de système d'exploitation. Il stocke par classe de structures telles que la course constante de temps de la piscine, de champ et de données de la méthode, et le code pour les méthodes et les constructeurs, y compris la des méthodes spéciales (§2.9) utilisés en classe et d'instance d'initialisation et de initialisation de l'interface.

Aussi, à propos de la méthode d'entrées

L' method_info structures représentent toutes les méthodes déclarées par ce de classe ou de type d'interface, y compris les méthodes d'instance, les méthodes de la classe, instance méthodes d'initialisation (§2.9), et toute la classe ou de l'interface méthode d'initialisation (§2.9). Les méthodes tableau ne comprend pas les éléments représentant des méthodes qui sont héritées de super-classes ou superinterfaces.

23voto

tucuxi Points 5130

En cas de doute, regardez la source (puits, d'une source; chaque JVM est libre de choisir la façon de le faire, que la norme n'exige pas la représentation interne). J'ai donc eu un coup d'oeil, et a trouvé le commentaire suivant dans la mise en œuvre de JDK 7-u60 de la JVM hotspot:

// A Klass is the part of the klassOop that provides:
//  1: language level class object (method dictionary etc.)
//  2: provide vm dispatch behavior for the object
// Both functions are combined into one C++ class. The toplevel class "Klass"
// implements purpose 1 whereas all subclasses provide extra virtual functions
// for purpose 2.

// One reason for the oop/klass dichotomy in the implementation is
// that we don't want a C++ vtbl pointer in every object.  Thus,
// normal oops don't have any virtual functions.  Instead, they
// forward all "virtual" functions to their klass, which does have
// a vtbl and does the C++ dispatch depending on the object's

La façon dont je l'ai lu, cela signifie que, pour cette (très populaire), mise en œuvre, des instances de l'objet seulement de stocker un pointeur vers leur classe. Le coût, par instance d'une classe, de la classe ayant une plus longue ou plus courte chaîne d'héritage est effectivement 0. Les classes elles-mêmes ne prennent de la place dans la mémoire (mais seulement une fois par classe). Au moment de l'exécution de l'efficacité de la profondeur de l'héritage des chaînes est une autre affaire.

4voto

Steve Jessop Points 166970

Une instance exige généralement les données suivantes, bien qu'il appartienne à la mise en œuvre exactement quoi faire:

  • les champs d'instance de la classe et de ses classes parentes, je suppose que vous n'avez pas moyen d'inclure dans le terme "frais généraux"
  • des moyens de verrouillage de l'objet
  • si le garbage collector déplace des objets, des moyens pour enregistrer l'original de hachage de l'objet (pour Object.hashCode)
  • certains moyens d'accéder à des informations de type

Comme vous le devinez dans votre question, dans un "normal" implémentation de Java le type d'informations est stocké par catégorie, par exemple. Partie de la définition de "type", c'est que les deux instances de la même classe ont nécessairement le même type d'informations, il n'y a pas de raison évidente de ne pas le partager. Si vous attendez que par exemple les frais généraux d'être constant, de ne pas dépendre de la hiérarchie de classe.

C'est-à-dire, en ajoutant plus de vide, des interfaces ou des classes d'une classe ne devrait pas augmenter la taille de ses instances. Je ne pense pas que ce soit la langue ou la JVM spec assure de fait ce, même si, pour ne pas faire trop d'hypothèses sur ce qu'est un "non-normale" implémentation de Java est autorisé à le faire.

En aparté, la deuxième et la troisième des choses sur ma liste peuvent être combinés par la ruse ruse, de sorte que tous les deux sont un seul pointeur. L'article que vous lien renvoie à des références en prenant 4 octets, donc 8 octets d'un objet est un pointeur vers le type de l'information, un champ contenant soit un hashcode ou un pointeur vers un moniteur, et probablement quelques-unes des options les plus faibles des 2 bits de l'un ou les deux de ces le pointeur de champs. Object va (vous attendez) être plus élevé sur une version 64 bits de Java.

2voto

user949300 Points 7954

Double et Integer, qui étendent Number, qui étend Object, n’ont pas de comportement O (n), c’est-à-dire qu’un Integer n’est pas 3 fois la taille d’un objet. Je pense donc que la réponse est O (1). par exemple, voir cette vieille question SO

1voto

EJP Points 113412

en théorie, la surcharge directement liée à la représentation en mémoire de tout objet Java devrait être O (1) pour la profondeur d'héritage N. Est-ce que quelqu'un sait si c'est vrai en pratique?

Il ne peut s'agir de O (1) que s'il n'y a aucun membre d'instance à chaque niveau. Chaque membre d'instance requiert de l'espace par instance.

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