Si bien la longitud de a Stringes teóricamente Integer.MAX_VALUE, la longitud de un literal de cadena en la fuente parece estar limitada a solo 65535 bytes de datos UTF-8.
200_success
Respuestas:
169
Teniendo en cuenta que el método de la Stringclase lengthdevuelve un int, la longitud máxima que devolvería el método sería Integer.MAX_VALUE, que es 2^31 - 1(o aproximadamente 2 mil millones).
Las variables contenidas en una matriz no tienen nombres; en su lugar, se hace referencia a ellas mediante expresiones de acceso a matriz que usan valores de índice de enteros no negativos. Estas variables se denominan
componentes de la matriz. Si una matriz tiene ncomponentes, decimos que nes la
longitud de la matriz; Se hace referencia a los componentes de la matriz utilizando índices enteros desde 0hasta n - 1, inclusive.
Además, la indexación debe ser por intvalores, como se menciona en la Sección 10.4 :
Las matrices deben indexarse por intvalores;
Por lo tanto, parece que el límite es 2^31 - 1, ya que ese es el valor máximo para un intvalor no negativo .
Sin embargo, probablemente habrá otras limitaciones, como el tamaño máximo asignable para una matriz.
Gran respuesta hombre! Eché un vistazo al código fuente String.java y está bien, 'contar' es la variable int que devuelve la longitud de la matriz de caracteres, y la matriz de caracteres se almacena en la variable 'valor' (como char []) Significa que el tamaño de la cadena podría ser de alrededor de 2 GB. Por supuesto, podría haber limitaciones para asignar ese tamaño de memoria. ¡Gracias!
taichi
55
Acabo de intentar definir un literal de cadena en un programa java de hello world que era más largo que 65546. javacda un error acerca de que ese literal es demasiado largo:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
dlamblin
2
@dlamblin: Eso suena como una limitación de la javacde Stringlos literales (no Stringobjetos), como no puedo encontrar ninguna referencia a los límites de tamaño de Stringliterales en la especificación del lenguaje Java y JVM especificación. Intenté hacer un Stringliteral que tuviera más de 100,000 caracteres, y el compilador de Eclipse no tuvo problemas para compilarlo. (Y ejecutar el programa fue capaz de mostrar que el literal tenía String.lengthmás de 100,000)
Coobird
3
@Premraj Fue hace tres años, así que tuve que pensarlo. ;) Lo que quería decir; para construir una cadena de tamaño máximo necesita mucha memoria, posiblemente más de la que tiene de todos modos. Necesita dos bytes por carácter ~ 4GB, pero necesita construir esto desde un StringBuilder o char [], lo que significa que necesita otros dos bytes por carácter para crearlo, es decir, otros ~ 4 GB (al menos temporalmente)
Peter Lawrey
25
java.io.DataInput.readUTF()y java.io.DataOutput.writeUTF(String)digamos que un Stringobjeto está representado por dos bytes de información de longitud y la representación UTF-8 modificada de cada carácter en la cadena. Esto concluye que la longitud de la cadena está limitada por el número de bytes de la representación UTF-8 modificada de la cadena cuando se usa con DataInputy DataOutput.
Además, la especificaciónCONSTANT_Utf8_info encontrada en la especificación de máquina virtual Java define la estructura de la siguiente manera.
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];}
Puede encontrar que el tamaño de 'longitud' es de dos bytes .
Que el tipo de retorno de un determinado método (p String.length(). Ej. ) intNo siempre significa que su valor máximo permitido es Integer.MAX_VALUE. En cambio, en la mayoría de los casos, intse elige solo por razones de rendimiento. La especificación del lenguaje Java dice que los enteros cuyo tamaño es más pequeño que el de intse convierten intantes del cálculo (si mi memoria me sirve correctamente) y es una razón para elegir intcuando no hay una razón especial.
La longitud máxima en el momento de la compilación es como máximo 65536. Observe nuevamente que la longitud es el número de bytes de la representación UTF-8 modificada , no el número de caracteres en un Stringobjeto.
Stringlos objetos pueden tener muchos más personajes en tiempo de ejecución. Sin embargo, si desea utilizar Stringobjetos DataInpute DataOutputinterfaces, es mejor evitar el uso de Stringobjetos demasiado largos . Encontré esta limitación cuando implementé Objective-C equivalentes de DataInput.readUTF()y DataOutput.writeUTF(String).
Como las matrices deben indexarse con enteros, la longitud máxima de una matriz es Integer.MAX_INT(2 31 -1, o 2 147 483 647). Esto supone que tiene suficiente memoria para contener una matriz de ese tamaño, por supuesto.
Tengo un iMac 2010 con 8GB de RAM, ejecutando Eclipse Neon.2 Release (4.6.2) con Java 1.8.0_25. Con el argumento VM -Xmx6g, ejecuté el siguiente código:
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());
Esto imprime:
Requested array size exceeds VM limit
1207959550
Entonces, parece que el tamaño máximo de la matriz es ~ 1,207,959,549. Entonces me di cuenta de que en realidad no nos importa si Java se queda sin memoria: solo estamos buscando el tamaño máximo de matriz (que parece ser una constante definida en alguna parte). Entonces:
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);}}
Que imprime:
Requested array size exceeds VM limit
Last:2147483647Last:0Requested array size exceeds VM limit
Last:2147483646Last:1Java heap space
Last:2147483645Last:2
Entonces, parece que el máximo es Integer.MAX_VALUE - 2, o (2 ^ 31) - 3
PD No estoy seguro de por qué mi StringBuildermáximo en 1207959550mientras que mi char[]máximo en (2 ^ 31) -3. Parece que AbstractStringBuilderduplica el tamaño de su interno char[]para hacerlo crecer, por lo que probablemente cause el problema.
La cadena se considera como matriz de caracteres internamente, por lo que la indexación se realiza dentro del rango máximo. Esto significa que no podemos indexar el miembro 2147483648, por lo que la longitud máxima de String en Java es 2147483647.
El tipo de datos primitivo int es de 4 bytes (32 bits) en java. Como 1 bit (MSB) se usa como bit de signo , el rango está restringido dentro de -2 ^ 31 a 2 ^ 31-1 (-2147483648 a 2147483647). No podemos usar valores negativos para la indexación, por lo que obviamente el rango que podemos usar es de 0 a 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);}}...}
Pero cuando la asignación de puntos de código> 1byte, llama al encodeUTF8método:
En este sentido, la longitud máxima de la cadena es 65535 bytes, es decir, la longitud de codificación utf-8. y no charcontar
Puede encontrar el rango de puntos de código Unicode modificado de JVM, desde el enlace utf8 struct anterior.
String
es teóricamenteInteger.MAX_VALUE
, la longitud de un literal de cadena en la fuente parece estar limitada a solo 65535 bytes de datos UTF-8.Respuestas:
Teniendo en cuenta que el método de la
String
claselength
devuelve unint
, la longitud máxima que devolvería el método seríaInteger.MAX_VALUE
, que es2^31 - 1
(o aproximadamente 2 mil millones).En términos de longitudes e indexación de matrices, (como
char[]
, probablemente, la forma en que se implementa la representación de datos internos paraString
s), el Capítulo 10: Matrices de la especificación del lenguaje Java, Java SE 7 Edition dice lo siguiente:Además, la indexación debe ser por
int
valores, como se menciona en la Sección 10.4 :Por lo tanto, parece que el límite es
2^31 - 1
, ya que ese es el valor máximo para unint
valor no negativo .Sin embargo, probablemente habrá otras limitaciones, como el tamaño máximo asignable para una matriz.
fuente
javac
da un error acerca de que ese literal es demasiado largo:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
javac
deString
los literales (noString
objetos), como no puedo encontrar ninguna referencia a los límites de tamaño deString
literales en la especificación del lenguaje Java y JVM especificación. Intenté hacer unString
literal que tuviera más de 100,000 caracteres, y el compilador de Eclipse no tuvo problemas para compilarlo. (Y ejecutar el programa fue capaz de mostrar que el literal teníaString.length
más de 100,000)java.io.DataInput.readUTF()
yjava.io.DataOutput.writeUTF(String)
digamos que unString
objeto está representado por dos bytes de información de longitud y la representación UTF-8 modificada de cada carácter en la cadena. Esto concluye que la longitud de la cadena está limitada por el número de bytes de la representación UTF-8 modificada de la cadena cuando se usa conDataInput
yDataOutput
.Además, la especificación
CONSTANT_Utf8_info
encontrada en la especificación de máquina virtual Java define la estructura de la siguiente manera.Puede encontrar que el tamaño de 'longitud' es de dos bytes .
Que el tipo de retorno de un determinado método (p
String.length()
. Ej. )int
No siempre significa que su valor máximo permitido esInteger.MAX_VALUE
. En cambio, en la mayoría de los casos,int
se elige solo por razones de rendimiento. La especificación del lenguaje Java dice que los enteros cuyo tamaño es más pequeño que el deint
se conviertenint
antes del cálculo (si mi memoria me sirve correctamente) y es una razón para elegirint
cuando no hay una razón especial.La longitud máxima en el momento de la compilación es como máximo 65536. Observe nuevamente que la longitud es el número de bytes de la representación UTF-8 modificada , no el número de caracteres en un
String
objeto.String
los objetos pueden tener muchos más personajes en tiempo de ejecución. Sin embargo, si desea utilizarString
objetosDataInput
eDataOutput
interfaces, es mejor evitar el uso deString
objetos demasiado largos . Encontré esta limitación cuando implementé Objective-C equivalentes deDataInput.readUTF()
yDataOutput.writeUTF(String)
.fuente
Como las matrices deben indexarse con enteros, la longitud máxima de una matriz es
Integer.MAX_INT
(2 31 -1, o 2 147 483 647). Esto supone que tiene suficiente memoria para contener una matriz de ese tamaño, por supuesto.fuente
Tengo un iMac 2010 con 8GB de RAM, ejecutando Eclipse Neon.2 Release (4.6.2) con Java 1.8.0_25. Con el argumento VM -Xmx6g, ejecuté el siguiente código:
Esto imprime:
Entonces, parece que el tamaño máximo de la matriz es ~ 1,207,959,549. Entonces me di cuenta de que en realidad no nos importa si Java se queda sin memoria: solo estamos buscando el tamaño máximo de matriz (que parece ser una constante definida en alguna parte). Entonces:
Que imprime:
Entonces, parece que el máximo es Integer.MAX_VALUE - 2, o (2 ^ 31) - 3
PD No estoy seguro de por qué mi
StringBuilder
máximo en1207959550
mientras que michar[]
máximo en (2 ^ 31) -3. Parece queAbstractStringBuilder
duplica el tamaño de su internochar[]
para hacerlo crecer, por lo que probablemente cause el problema.fuente
aparentemente está vinculado a un int, que es 0x7FFFFFFF (2147483647).
fuente
El tipo de retorno del método length () de la clase String es int .
Consulte http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()
Entonces el valor máximo de int es 2147483647 .
La cadena se considera como matriz de caracteres internamente, por lo que la indexación se realiza dentro del rango máximo. Esto significa que no podemos indexar el miembro 2147483648, por lo que la longitud máxima de String en Java es 2147483647.
El tipo de datos primitivo int es de 4 bytes (32 bits) en java. Como 1 bit (MSB) se usa como bit de signo , el rango está restringido dentro de -2 ^ 31 a 2 ^ 31-1 (-2147483648 a 2147483647). No podemos usar valores negativos para la indexación, por lo que obviamente el rango que podemos usar es de 0 a 2147483647.
fuente
Como se menciona en la respuesta de Takahiko Kawasaki , java representa cadenas Unicode en forma de UTF-8 modificado y en la estructura JSTM-Spec CONSTANT_UTF8_info , se asignan 2 bytes a la longitud (y no el número de caracteres de la cadena).
Para extender la respuesta, el método de la biblioteca de bytecode jvm de ASM contiene esto:
putUTF8
Pero cuando la asignación de puntos de código> 1byte, llama al
encodeUTF8
método:En este sentido, la longitud máxima de la cadena es 65535 bytes, es decir, la longitud de codificación utf-8. y no
char
contarPuede encontrar el rango de puntos de código Unicode modificado de JVM, desde el enlace utf8 struct anterior.
fuente