Question

Si vous avez deux instances d'une chaîne, et ils sont égaux, en Java, ils partagent la même mémoire. Comment est-ce mis en œuvre sous le capot?

EDIT: Mon application utilise un grand nombre d'objets String, dont beaucoup sont identiques. Quelle est la meilleure façon d'utiliser String Java pool constante, pour éviter de créer la mise en œuvre de poids mouche personnalisée?

Était-ce utile?

La solution

Regardez le code source de java.lang.String (la source de toute api java fait partie du JDK).

Pour résumer: Une chaîne enveloppe une séquence d'un char[]. Ce char[] support est jamais modifié. Ceci est accompli par ne fuit ni capturer cette char[] en dehors de la classe String. Cependant, plusieurs Strings peuvent partager le même char[] (voir la mise en œuvre de String.substring).

Il y a aussi le mécanisme d'interner, comme expliqué dans les autres réponses.

Autres conseils

  

Si vous avez deux instances d'une chaîne, et ils sont égaux, en Java, ils partagent la même mémoire

Ceci est en fait pas 100% vrai.

Ce blog est une explication décente pourquoi il en est ainsi, et ce que le piscine Chaîne constante est.

littéraux chaîne sont interné en Java, donc il n'y a vraiment qu'un seul objet Chaîne avec plusieurs références (quand ils sont égaux, ce qui est toujours le cas). Voir l'article java.net Tout à propos de stagiaire () pour plus de détails.

Il y a aussi un bon exemple / explication dans la section 3.10.5 littéraux de chaîne des JLS qui parle lorsque les chaînes sont internées et quand ils seront distincts.

Ce n'est pas nécessaire vrai. Exemple:

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true

:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false

Maintenant, la deuxième forme est déconseillée. Certains (y compris moi) pensent que String ne devrait même pas avoir un constructeur public. Une meilleure version de ce qui précède serait:

String s1 = new String("hello").intern();
String s2 = new String("hello").intern();
System.out.println(s1 == s2); // true

Il est évident que vous n'avez pas besoin de faire cela pour une String constante. Il est illustrative.

Le point important à ce sujet est que si vous êtes passé un String ou obtenir un à partir d'une fonction vous ne pouvez pas compter sur le String être canonique . canonique Object satisfait à cette égalité:

a.equals(b) == b.equals(a) == (a == b)

pour les instances non null a, b, d'un Class donné.

Pour répondre à votre question éditée, Sun JVMs ont une option -XX:+StringCache, qui, à mon observation peut réduire l'empreinte mémoire d'une application lourde chaîne de manière significative.

Dans le cas contraire, vous avez la possibilité d'interner vos cordes, mais je serais prudent. Les chaînes qui sont très grandes et plus référencé sera toujours utiliser la mémoire pour la vie de la machine virtuelle Java.

Modifier (en réponse à un commentaire): J'ai d'abord découvert l'option StringCache Tom Hawtin décrit un certain type de mise en cache pour améliorer certains points de référence. Mon observation quand je l'ai mis sur idée était que l'empreinte mémoire (après une collecte des ordures complète) a chemin vers le bas sur ne pas l'avoir. Il est pas un paramètre documenté, et peut en effet être juste sur l'optimisation de certains points de référence. Mon observation est que cela a aidé, mais je ne construirait pas un système important sur cette base.

Deux choses à faire attention à:

  1. Ne pas utiliser constructeur new String("abc"), il suffit d'utiliser le "abc" littéral.
  2. Apprendre à utiliser ( ) méthode dans la classe String. En particulier, lors de la concaténation des chaînes de caractères lors de la conversion ou tableau de caractères / tableau d'octets / etc String.

retourne intern() toujours des chaînes qui sont mises en commun.

Si vos chaînes identiques proviennent d'un ensemble fixe de valeurs possibles, puis un Enumeration Type-Safe est ce que vous voulez ici. Non seulement il réduire votre nombre de chaînes, mais il fera pour une application plus solide. Votre application entière saura cette chaîne a une sémantique attaché à, peut-être même des méthodes pratiques.

Mes optimisations préférées sont toujours celles qui peuvent être défendues comme faisant le code mieux , pas seulement plus rapide. Et 9 fois sur 10, le remplacement d'une chaîne avec un conduit de type béton à code plus correct et auto-documenté.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top