Alors que la longueur de a Stringest théoriquement Integer.MAX_VALUE, la longueur d'un littéral de chaîne dans la source semble être limitée à seulement 65 535 octets de données UTF-8.
200_success
Réponses:
169
Compte tenu des Stringclasses lengthméthode renvoie un int, la longueur maximale qui serait renvoyée par la méthode serait Integer.MAX_VALUE, qui est 2^31 - 1(ou environ 2 milliards).
Les variables contenues dans un tableau n'ont pas de nom; à la place, ils sont référencés par des expressions d'accès au tableau qui utilisent des valeurs d'index d'entiers non négatifs. Ces variables sont appelées les
composants du tableau. Si un tableau a des ncomposants, nous disons nest la
longueur du tableau; les composants du tableau sont référencés à l'aide d'indices entiers de 0à n - 1, inclus.
De plus, l'indexation doit se faire par intvaleurs, comme mentionné dans la section 10.4 :
Les tableaux doivent être indexés par des intvaleurs;
Par conséquent, il apparaît que la limite est effectivement 2^31 - 1, car il s'agit de la valeur maximale pour une intvaleur non négative .
Cependant, il y aura probablement d'autres limitations, telles que la taille maximale allouable pour un tableau.
Bonne réponse homme! J'ai jeté un coup d'œil sur le code source de String.java et c'est vrai, 'count' est la variable int qui renvoie la longueur du tableau char, et le tableau char est stocké sur la variable 'value' (comme char []) Cela signifie que la taille de la chaîne pourrait être d'environ 2 Go. Bien sûr, il pourrait y avoir des limitations pour allouer une telle taille de mémoire. Merci!
taichi
5
J'ai juste essayé de définir un littéral de chaîne dans un programme java hello world qui était plus long que 65546. javacdonne une erreur sur le fait que ce littéral est trop long:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
dlamblin
2
@dlamblin: Cela sonne comme une limitation de javacpour Stringlittéraux (pas des Stringobjets), que je ne peux trouver aucune référence à des limites de taille à Stringlittéraux dans la spécification du langage Java et JVM spécification. J'ai essayé de créer un Stringlittéral de plus de 100 000 caractères et le compilateur Eclipse n'a pas eu de problème pour le compiler. (Et l'exécution du programme a pu montrer que le littéral avait un String.lengthplus grand que 100000.)
coobird
3
@Premraj C'était il y a trois ans alors j'ai dû y réfléchir. ;) Ce que je voulais dire, c'était; pour construire une chaîne de taille maximale, vous avez besoin de beaucoup de mémoire, peut-être plus que ce que vous avez de toute façon. Vous avez besoin de deux octets par caractère ~ 4 Go, mais vous devez le construire à partir d'un StringBuilder ou char [] ce qui signifie que vous avez besoin de deux octets supplémentaires par caractère pour le créer en premier lieu, c'est-à-dire un autre ~ 4 Go (au moins temporairement)
Peter Lawrey
25
java.io.DataInput.readUTF()et java.io.DataOutput.writeUTF(String)dire qu'un Stringobjet est représenté par deux octets d'informations de longueur et la représentation UTF-8 modifiée de chaque caractère de la chaîne. Cela conclut que la longueur de String est limitée par le nombre d'octets de la représentation UTF-8 modifiée de la chaîne lorsqu'elle est utilisée avec DataInputet DataOutput.
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];}
Vous pouvez constater que la taille de «longueur» est de deux octets .
Le fait que le type de retour d'une certaine méthode (par exemple String.length()) soit intne signifie pas toujours que sa valeur maximale autorisée est Integer.MAX_VALUE. Au lieu de cela, dans la plupart des cas, intest choisi uniquement pour des raisons de performances. La spécification du langage Java dit que les entiers dont la taille est inférieure à celle de intsont convertis en intavant le calcul (si ma mémoire est bonne) et c'est une raison de choisir intquand il n'y a pas de raison particulière.
La longueur maximale au moment de la compilation est au maximum de 65 536. Notez à nouveau que la longueur est le nombre d'octets de la représentation UTF-8 modifiée , et non le nombre de caractères dans un Stringobjet.
Stringles objets peuvent avoir beaucoup plus de caractères lors de l'exécution. Cependant, si vous souhaitez utiliser des Stringobjets avec des interfaces DataInputet DataOutput, il vaut mieux éviter d'utiliser des Stringobjets trop longs . J'ai trouvé cette limitation lorsque j'ai implémenté des équivalents Objective-C de DataInput.readUTF()et DataOutput.writeUTF(String).
Étant donné que les tableaux doivent être indexés avec des entiers, la longueur maximale d'un tableau est Integer.MAX_INT(2 31 -1 ou 2 147 483 647). Cela suppose que vous ayez suffisamment de mémoire pour contenir un tableau de cette taille, bien sûr.
J'ai un iMac 2010 avec 8 Go de RAM, exécutant Eclipse Neon.2 Release (4.6.2) avec Java 1.8.0_25. Avec l'argument VM -Xmx6g, j'ai exécuté le code suivant:
StringBuilder sb =newStringBuilder();for(int i =0; i <Integer.MAX_VALUE; i++){try{
sb.append('a');}catch(Throwable e){System.out.println(i);break;}}System.out.println(sb.toString().length());
Cela imprime:
Requested array size exceeds VM limit
1207959550
Il semble donc que la taille maximale du tableau soit de ~ 1,207,959,549. Ensuite, j'ai réalisé que nous ne nous soucions pas vraiment de savoir si Java manquait de mémoire: nous cherchons simplement la taille maximale du tableau (qui semble être une constante définie quelque part). Alors:
for(int i =0; i <1_000; i++){try{char[] array =newchar[Integer.MAX_VALUE - i];Arrays.fill(array,'a');String string =newString(array);System.out.println(string.length());}catch(Throwable e){System.out.println(e.getMessage());System.out.println("Last: "+(Integer.MAX_VALUE - i));System.out.println("Last: "+ i);}}
Quelles impressions:
Requested array size exceeds VM limit
Last:2147483647Last:0Requested array size exceeds VM limit
Last:2147483646Last:1Java heap space
Last:2147483645Last:2
Donc, il semble que le maximum soit Integer.MAX_VALUE - 2, ou (2 ^ 31) - 3
PS Je ne sais pas pourquoi mon StringBuildermaximum a été atteint alors 1207959550que mon char[]maximum a atteint (2 ^ 31) -3. Il semble que AbstractStringBuilderdouble la taille de son interne char[]pour le faire croître, ce qui cause probablement le problème.
La chaîne est considérée comme un tableau de caractères en interne, donc l'indexation est effectuée dans la plage maximale. Cela signifie que nous ne pouvons pas indexer le 2147483648th membre. La longueur maximale de String en java est donc 2147483647.
Le type de données primitif int est de 4 octets (32 bits) en java. Comme 1 bit (MSB) est utilisé comme bit de signe , la plage est limitée entre -2 ^ 31 à 2 ^ 31-1 (-2147483648 à 2147483647). Nous ne pouvons pas utiliser de valeurs négatives pour l'indexation, donc évidemment la plage que nous pouvons utiliser va de 0 à 2147483647.
publicByteVector putUTF8(finalString stringValue){int charLength = stringValue.length();if(charLength >65535){// If no. of characters> 65535, than however UTF-8 encoded length, wont fit in 2 bytes.thrownewIllegalArgumentException("UTF8 string too large");}for(int i =0; i < charLength;++i){char charValue = stringValue.charAt(i);if(charValue >='\u0001'&& charValue <='\u007F'){// Unicode code-point encoding in utf-8 fits in 1 byte.
currentData[currentLength++]=(byte) charValue;}else{// doesnt fit in 1 byte.
length = currentLength;return encodeUtf8(stringValue, i,65535);}}...}
Mais lorsque le mappage de point de code> 1 octet, il appelle la encodeUTF8méthode:
En ce sens, la longueur maximale de la chaîne est de 65 535 octets, c'est-à-dire la longueur de codage utf-8. and not charcount
Vous pouvez trouver la plage de points de code Unicode modifiée de JVM, à partir du lien struct utf8 ci-dessus.
String
est théoriquementInteger.MAX_VALUE
, la longueur d'un littéral de chaîne dans la source semble être limitée à seulement 65 535 octets de données UTF-8.Réponses:
Compte tenu des
String
classeslength
méthode renvoie unint
, la longueur maximale qui serait renvoyée par la méthode seraitInteger.MAX_VALUE
, qui est2^31 - 1
(ou environ 2 milliards).En termes de longueurs et d'indexation des tableaux, (comme
char[]
, qui est probablement la façon dont la représentation des données internes est implémentée pourString
s), le chapitre 10: Tableaux de la spécification du langage Java, Java SE 7 Edition dit ce qui suit:De plus, l'indexation doit se faire par
int
valeurs, comme mentionné dans la section 10.4 :Par conséquent, il apparaît que la limite est effectivement
2^31 - 1
, car il s'agit de la valeur maximale pour uneint
valeur non négative .Cependant, il y aura probablement d'autres limitations, telles que la taille maximale allouable pour un tableau.
la source
javac
donne une erreur sur le fait que ce littéral est trop long:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
javac
pourString
littéraux (pas desString
objets), que je ne peux trouver aucune référence à des limites de taille àString
littéraux dans la spécification du langage Java et JVM spécification. J'ai essayé de créer unString
littéral de plus de 100 000 caractères et le compilateur Eclipse n'a pas eu de problème pour le compiler. (Et l'exécution du programme a pu montrer que le littéral avait unString.length
plus grand que 100000.)java.io.DataInput.readUTF()
etjava.io.DataOutput.writeUTF(String)
dire qu'unString
objet est représenté par deux octets d'informations de longueur et la représentation UTF-8 modifiée de chaque caractère de la chaîne. Cela conclut que la longueur de String est limitée par le nombre d'octets de la représentation UTF-8 modifiée de la chaîne lorsqu'elle est utilisée avecDataInput
etDataOutput
.En outre, la spécification de
CONSTANT_Utf8_info
trouvée dans la spécification de machine virtuelle Java définit la structure comme suit.Vous pouvez constater que la taille de «longueur» est de deux octets .
Le fait que le type de retour d'une certaine méthode (par exemple
String.length()
) soitint
ne signifie pas toujours que sa valeur maximale autorisée estInteger.MAX_VALUE
. Au lieu de cela, dans la plupart des cas,int
est choisi uniquement pour des raisons de performances. La spécification du langage Java dit que les entiers dont la taille est inférieure à celle deint
sont convertis enint
avant le calcul (si ma mémoire est bonne) et c'est une raison de choisirint
quand il n'y a pas de raison particulière.La longueur maximale au moment de la compilation est au maximum de 65 536. Notez à nouveau que la longueur est le nombre d'octets de la représentation UTF-8 modifiée , et non le nombre de caractères dans un
String
objet.String
les objets peuvent avoir beaucoup plus de caractères lors de l'exécution. Cependant, si vous souhaitez utiliser desString
objets avec des interfacesDataInput
etDataOutput
, il vaut mieux éviter d'utiliser desString
objets trop longs . J'ai trouvé cette limitation lorsque j'ai implémenté des équivalents Objective-C deDataInput.readUTF()
etDataOutput.writeUTF(String)
.la source
Étant donné que les tableaux doivent être indexés avec des entiers, la longueur maximale d'un tableau est
Integer.MAX_INT
(2 31 -1 ou 2 147 483 647). Cela suppose que vous ayez suffisamment de mémoire pour contenir un tableau de cette taille, bien sûr.la source
J'ai un iMac 2010 avec 8 Go de RAM, exécutant Eclipse Neon.2 Release (4.6.2) avec Java 1.8.0_25. Avec l'argument VM -Xmx6g, j'ai exécuté le code suivant:
Cela imprime:
Il semble donc que la taille maximale du tableau soit de ~ 1,207,959,549. Ensuite, j'ai réalisé que nous ne nous soucions pas vraiment de savoir si Java manquait de mémoire: nous cherchons simplement la taille maximale du tableau (qui semble être une constante définie quelque part). Alors:
Quelles impressions:
Donc, il semble que le maximum soit Integer.MAX_VALUE - 2, ou (2 ^ 31) - 3
PS Je ne sais pas pourquoi mon
StringBuilder
maximum a été atteint alors1207959550
que monchar[]
maximum a atteint (2 ^ 31) -3. Il semble queAbstractStringBuilder
double la taille de son internechar[]
pour le faire croître, ce qui cause probablement le problème.la source
apparemment, il est lié à un int, qui est 0x7FFFFFFF (2147483647).
la source
Le type de retour de la méthode length () de la classe String est int .
Reportez-vous à http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()
La valeur maximale de int est donc 2147483647 .
La chaîne est considérée comme un tableau de caractères en interne, donc l'indexation est effectuée dans la plage maximale. Cela signifie que nous ne pouvons pas indexer le 2147483648th membre. La longueur maximale de String en java est donc 2147483647.
Le type de données primitif int est de 4 octets (32 bits) en java. Comme 1 bit (MSB) est utilisé comme bit de signe , la plage est limitée entre -2 ^ 31 à 2 ^ 31-1 (-2147483648 à 2147483647). Nous ne pouvons pas utiliser de valeurs négatives pour l'indexation, donc évidemment la plage que nous pouvons utiliser va de 0 à 2147483647.
la source
Comme mentionné dans la réponse de Takahiko Kawasaki , java représente les chaînes Unicode sous la forme d' UTF-8 modifié et dans la structure JVM-Spec CONSTANT_UTF8_info , 2 octets sont alloués à la longueur (et non au nombre de caractères de String).
Pour étendre la réponse, la méthode de la bibliothèque de bytecode jvm ASM contient ceci:
putUTF8
Mais lorsque le mappage de point de code> 1 octet, il appelle la
encodeUTF8
méthode:En ce sens, la longueur maximale de la chaîne est de 65 535 octets, c'est-à-dire la longueur de codage utf-8. and not
char
countVous pouvez trouver la plage de points de code Unicode modifiée de JVM, à partir du lien struct utf8 ci-dessus.
la source