Concernant ma question précédente, Pourquoi == les comparaisons avec Integer.valueOf (String) donnent-elles des résultats différents pour 127 et 128? , nous savons que Integer
class
a un cache qui stocke des valeurs comprises entre -128
et 127
.
Je me demandais simplement pourquoi entre -128 et 127?
La documentation Integer.valueOf () indique que c'est "mettant en cache les valeurs fréquemment demandées} _". Mais est-ce que les valeurs entre -128
et 127
sont souvent demandées pour de vrai? Je pensais que les valeurs fréquemment demandées sont très subjectives.
Y a-t-il une raison possible derrière cela?
La documentation indique également: ".. et peut mettre en cache d'autres valeurs en dehors de cette plage."
Comment cela peut-il être réalisé?
Je me demandais pourquoi entre -128 et 127?
Un plus grand nombre d'entiers peut être mis en cache, mais au moins ceux compris entre -128 et 127 doivent être mis en cache car il est requis par le Spécification du langage Java (l'emphase mienne):
Si la valeur p qui est encadrée est vraie, fausse, un octet ou un caractère compris entre\u0000 et\u007f, ou un nombre entier ou court compris entre -128 et 127 (inclus), alors soit r1 et r2 les résultats de deux conversions quelconques de p. Il est toujours le cas que r1 == r2.
La justification de cette exigence est expliquée dans le même paragraphe:
Idéalement, la mise en boîte d'une valeur primitive donnée p devrait toujours donner une référence identique. En pratique, cela peut ne pas être réalisable avec les techniques de mise en œuvre existantes. Les règles ci-dessus sont un compromis pragmatique. La dernière clause ci-dessus exige que certaines valeurs communes soient toujours regroupées dans des objets impossibles à distinguer. [...]
Ceci garantit que, dans la plupart des cas, le comportement sera celui souhaité, sans imposer de pénalité de performances indue, en particulier sur les petits périphériques. Des implémentations moins limitées en mémoire peuvent, par exemple, mettre en cache toutes les valeurs char et short, ainsi que les valeurs int et long dans la plage de -32K à + 32K.
Comment puis-je mettre en cache d'autres valeurs en dehors de cette plage?
Vous pouvez utiliser l'option JVM -XX:AutoBoxCacheMax
, qui n'est pas vraiment documentée dans la liste des options JVM Hotspot disponibles . Cependant, il est mentionné dans les commentaires dans la classe Integer
autour de la ligne 590 :
La taille du cache peut être contrôlée par l'option
-XX:AutoBoxCacheMax=<size>
.
Notez que ceci est spécifique à l'implémentation et peut être disponible ou non sur d'autres machines virtuelles.
-128 à 127 est la taille par défaut. Mais javadoc indique également que la taille du cache Integer peut être contrôlée par l’option -XX:AutoBoxCacheMax=<size>
. Notez qu'il ne définit que la valeur haute, la valeur basse est toujours -128. Cette fonctionnalité a été introduite dans 1.6.
Quant à pourquoi -128 à 127 - il s’agit d’une plage de valeurs en octets et il est naturel de l’utiliser pour un très petit cache.
Si c'est ce que vous demandez, la raison pour la mise en cache de petits entiers est que beaucoup d'algorithmes utilisent de petits entiers dans leurs calculs. Il est donc préférable d'éviter la surcharge liée à la création d'objet pour ces valeurs.
La question devient alors quels entiers à mettre en cache. Encore une fois, en général, la fréquence avec laquelle les valeurs constantes sont utilisées a tendance à diminuer à mesure que la valeur absolue de la constante augmente - tout le monde passe beaucoup de temps en utilisant les valeurs 1, 2 ou 10, relativement peu d’utilisateurs utilisent la valeur 109. intensivement; Les performances seront moins nombreuses en fonction de la rapidité avec laquelle on peut obtenir un entier pour 722. Java a choisi d'allouer 256 emplacements couvrant la plage d'une valeur d'octet signé. Cette décision a peut-être été éclairée par l’analyse de programmes existants à l’époque, mais il est tout aussi probable qu’elle ait été purement arbitraire. C'est un espace raisonnable à investir, il est facile d'y accéder rapidement (masque pour savoir si la valeur est dans la plage du cache, puis recherche rapide dans un tableau pour accéder au cache), et il couvrira certainement les cas les plus courants.
En d'autres termes, je pense que la réponse à votre question est "ce n'est pas aussi subjectif que vous le pensiez, mais les limites exactes sont en grande partie une décision empirique ... et des preuves expérimentales ont été apportées, à savoir que c'était assez bon. "
La valeur entière maximale pouvant être mise en cache peut être configurée via la propriété système i.e Java.lang.Integer.IntegerCache.high
(-XX:AutoBoxCacheMax
). Le cache est implémenté à l'aide d'un tableau.
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
Lorsque vous rencontrez avec la classe Integer et toujours encadré dans la plage -128 à 127, il est toujours préférable de convertir l'objet Integer en valeur int comme ci-dessous.
<Your Integer Object>.intValue()