8
votes

Taille de la chaîne Java vide

J'ai entendu un collègue dire que je paierais "24 octets" si j'ai laissé tomber un membre de chaîne dans une classe Java, même si la chaîne est vide. Est-ce exacte? Est-ce la même chose pour entier, flotter, double? (par opposition à int, flotter, double, qui ne serait que 4, 4 et 8 octets chacun).


0 commentaires

4 Réponses :


16
votes

Vous paierez 4 ou 8 octets pour la référence . Si vous paierez pour un objet supplémentaire par instance de votre objet "conteneur" dépend de la manière dont vous obtenez votre chaîne vide. Par exemple, si vous utilisez le littéral "" ", alors tous les les instances se réfèrent au même objet, vous ne devez donc payer que la référence elle-même.

Si vous créez une chaîne vide distincte pour chaque instance, alors cela prendra évidemment plus de mémoire.


19 commentaires

Donc, ce n'est pas le cas que la référence elle-même pèse 24 octets - je pense que c'est ce qu'il suggérait. Phew. J'ai trouvé que trop lourd.


@Frank: S'il vous suggère vraiment que, je serais un peu méfiant de tout ce qu'il dit ...


@Jon Skeet Pouvez-vous répondre à cette question .... Stackoverflow.com/Questtions/11700320/...


Frank, je doute qu'il suggère ce que vous dites parce que 24 est effectivement le nombre d'octets que vous payez pour une instance plaine et vide de objet sur un point d'accès 64 bits typique. Vous payez le même montant pour un entier .


@Kumarvivekmitra: Vous avez déjà une excellente réponse.


@ Jon, je suis peut-être vraiment stupide de conclure la réponse, je veux dire qui la réponse a-t-elle prouver raison, Kathy Sierra ou Corey McGlone


@Kumarvivekmitra: Je n'ai pas regardé en détail, pour être honnête - je n'ai pas le temps en ce moment.


@Kumarvivekmitra sollicitation de ce genre est vraiment inapproprié.


@Marko - alors, il avait raison, juste écrire "String X" coûte 24 octets, les 24 octets de l'objet?


@Frank: Non, pour les raisons spécifiées dans ma réponse.


Oui, je ne l'obtiens pas. Je pensais que la chaîne dérivée de l'objet? J'ai téléchargé la source d'Openjdk pour aller au bas de cela. Il y a quelque chose que je ne comprends pas des "références" et des "instances d'objet"


Frank, c'est là où il n'était pas à droite, mais je doute toujours qu'il voulait dire la taille de la référence. Il vient de confondre la Déclaration avec l'objet réel, il va probablement faire référence à --- et oublié des cordes qui sont immuables, donc largement partagées, notamment à travers la piscine constante.


@FRANK: Si vous êtes confondu entre des références et des objets, je ne serait pas Démarrer la transmission dans le code source JDK. Cela va ajouter à votre confusion plutôt que de vous aider. Lisez un bon didacticiel Java qui expliquera la différence.


Jon - Je regarde la source ... Bien sûr, je ne sais pas ce que le compilateur fait, mais String a 4 membres privés. Je vais ouvrir un autre fil pour essayer de comprendre comment le compilateur fonctionne avec les réfs.


@FRANK: Ce n'est pas une question de savoir comment le compilateur fonctionne avec des références. Cela comprend la différence entre les références et les objets. Lorsque votre classe a un champ de type chaîne , cette valeur de champ juste est une référence. C'est pas un objet. La valeur pourrait se référer à un objet (ou être null), mais il pourrait y avoir plusieurs autres références au même objet également.


Oui, je comprends ça. Je suis habitué au modèle C ++, où si je mets quelque chose dans la Déclaration d'une classe, je connais la mise en page de la mémoire (plus ou moins) et peut même évaluer le nombre d'octets que chaque instance prend (ce qui peut être très utile dans certains environnements. ).


@Frank: Droite. Vous devez penser différemment. Java n'est pas C ++ et tente de raisonner à ce sujet comme si c'était était C ++ sera toujours douloureux. Le plus proche que vous viendrez est de penser à un champ string comme étant un peu comme A std: string * champ en C ++.


Quel est le meilleur ou stocker une chaîne null ou vide?


@nitinsridar: Cela dépend entièrement du contexte. C'est comme demander si les entiers sont meilleurs que les numéros de points flottants ou non.



0
votes

C'est vrai que vous allez payer beaucoup plus pour un entier que pour un int. Je me souviens de vérifier quelques versions Java en arrière et l'entier a pris environ 24 octets plus. Tant que vous avez la chaîne pointant sur un objet NULL (AKA sur rien), vous gardez uniquement un pointeur en mémoire et je ne pense pas que le JVM préservera un emplacement pour l'initialiser auquel cas vous n'êtes pas Perdre 24 octets, juste 8. Si vous créez la chaîne si vous créez (même la chaîne vide ""), vous avez déjà un objet en mémoire et, étant donné que tous les objets héritent de l'objet, ils sont livrés avec des bagages et occupent plus de mémoire que vous n'attendez pas . En fonction de votre utilisation de la chaîne, une solution commune consiste à commencer par un objet NULL et la plus paresseuse l'initialise lorsque vous en avez besoin.


3 commentaires

70 octets, c'est bien. Vous payez pour la référence (typiquement seulement 4 octets -, même Steven jusqu'à présent) et 24 octets pour l'objet sur le tas.


Cela a plus de sens, je me souvenais surtout que l'entier prenant beaucoup plus que j'ai réimprimé LinkedList avec Int.


Oui, LinkedList est un porc de mémoire connu. ArrayList est beaucoup mieux à cet égard.



1
votes

emprunté à Cette réponse : Le programme imprime 32 octets pour la chaîne vide (et 0 pour "" qui est dans le pool de string).

public static void main(String... args) {
    long free1 = free();
    String s = "";
    long free2 = free();
    String s2 = new String("");
    long free3 = free();
    if (free3 == free1) System.err.println("You need to use -XX:-UseTLAB");
    System.out.println("\"\" took " + (free1 - free2) + " bytes and new String(\"\") took " + (free2
            - free3) + " bytes.");
}

private static long free() {
    return Runtime.getRuntime().freeMemory();
}


3 commentaires

Le tableau de charcuterie vide de nouvelle chaîne ("") est partagé. Nouvelle chaîne ("x") donne 72 octets.


@ R.MOeller c'est un bon point - mais je suis à peu près sûr que la chaîne vide sera toujours dans le pool de cordes, même si vous ne l'utilisez pas explicitement (il est probablement utilisé dans de nombreuses instances À travers le code interne JDK) ... Donc cela dépend de ce que vous voulez mesurer.


Je pense que c'est le tableau de charcuterie de la longueur zéro qui est partagé .. une nouvelle chaîne ("") crée une nouvelle chaîne mais ne crée pas de tableau de caractères. Ainsi, 24 octets est la longueur de la chaîne vide, mais la longueur de la chaîne de 1 longueur est> 72 octets



2
votes

La chaîne est composée de l'en-tête d'objet (2 mots sur Hotspot, 3 sur J9), sur le champ Int et la référence de tableau de caractères. Le tableau de charme lui-même est composé d'en-tête, d'Int Int et du reste du tableau. Tout est rembourré à 8 octets. Habituellement, les caractères sont codés avec 2 octets par char. Certains JVMS peuvent utiliser des codages alternatifs pour le char. À un moment donné, J9 pourrait encoder des chaînes dans UTF8. Hotspot moderne utilisera 1 octet par caractère si la chaîne est composée de caractères simples (essentiellement 1 octet codé des glyphes de UTF-8, tels que l'alphabet anglais, les nombres et tels). Sinon, il utilise 2 octets par caractère pour toute une matrice.

Taille si profonde de la taille de la chaîne vide est donc:

  • 32 octets sur hotspot 32 bits (16 octets pour chaîne, 16 octets pour Char [])
  • 56 octets sur 64 bits Hotspot (32 octets pour chaîne, 24 octets pour Char [])
  • 40 octets sur 64 bits Hotspot avec références comprimées (24 octets pour chaîne, 16 octets pour char [])

    Communément, la matrice de caractère vide ne sera pas allouée car sa valeur sera déduite. Après tout, tous les tableaux de caractères vides sont égaux. Donc, une pénalité réelle pour une chaîne vide sera une taille de chaîne peu profonde; qui est 24 octets pour la plupart des situations communes aujourd'hui (point d'accès 64 bits avec REF comprimé).

    IBM J9 JVM a un plus grand nombre d'objets et il allouera un peu plus.


0 commentaires