Enquanto o comprimento de a Stringé teoricamente Integer.MAX_VALUE, o comprimento de uma string literal na origem parece estar limitado a apenas 65535 bytes de dados UTF-8.
200_success
Respostas:
169
Considerando que o método da Stringclasse lengthretorna um int, o comprimento máximo que seria retornado pelo método seria Integer.MAX_VALUE, que é 2^31 - 1(ou aproximadamente 2 bilhões).
As variáveis contidas em uma matriz não têm nomes; em vez disso, eles são referenciados por expressões de acesso à matriz que usam valores de índice inteiro não negativo. Essas variáveis são chamadas de
componentes da matriz. Se uma matriz tem ncomponentes, dizemos que né o
comprimento da matriz; os componentes da matriz são referenciados usando índices inteiros de 0até n - 1, inclusive.
Além disso, a indexação deve ser por intvalores, conforme mencionado na Seção 10.4 :
Matrizes devem ser indexadas por intvalores;
Portanto, parece que o limite é realmente 2^31 - 1, pois esse é o valor máximo para um intvalor não negativo .
No entanto, provavelmente haverá outras limitações, como o tamanho máximo alocável para uma matriz.
Ótima resposta, cara! Dei uma olhada no código-fonte String.java e está certo, 'count' é a variável int que retorna o comprimento da matriz char, e a matriz char é armazenada na variável 'value' (como char []). que o tamanho da String pode estar em torno de 2 GB. Obviamente, pode haver limitações para alocar esse tamanho de memória. Obrigado!
taichi
5
Eu apenas tentei definir um literal cadeia de caracteres em um programa java Olá mundo que era mais do que 65546. javacdá um erro sobre esse ser literal muito longo:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
dlamblin
2
@ dlamblin: Isso soa como uma limitação javacpara Stringliterais (não Stringobjetos), já que não consigo encontrar nenhuma referência aos limites de tamanho para Stringliterais na Java Language Specification e na JVM Specification. Tentei criar um Stringliteral com mais de 100.000 caracteres e o compilador Eclipse não teve problemas ao compilá-lo. (E, correndo o programa foi capaz de mostrar que o literal teve uma String.lengthmaior do que 100.000.)
coobird
3
@ Premraj Foi há três anos, então eu tive que pensar sobre isso. ;) O que eu quis dizer foi; Para criar uma cadeia de tamanho máximo, você precisa de muita memória, possivelmente mais do que você possui. Você precisa de dois bytes por caractere ~ 4 GB, mas precisa construí-lo a partir de um StringBuilder ou char [], o que significa que você precisa de mais dois bytes por caractere para criá-lo em primeiro lugar, ou seja, outros ~ 4 GB (pelo menos temporariamente)
Peter Lawrey
25
java.io.DataInput.readUTF()e java.io.DataOutput.writeUTF(String)diga que um Stringobjeto é representado por dois bytes de informações de comprimento e pela representação UTF-8 modificada de cada caractere na sequência. Isso conclui que o comprimento da String é limitado pelo número de bytes da representação UTF-8 modificada da string quando usada com DataInpute DataOutput.
Além disso, a especificaçãoCONSTANT_Utf8_info encontrada na especificação da máquina virtual Java define a estrutura da seguinte maneira.
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];}
Você pode achar que o tamanho do 'comprimento' é de dois bytes .
Que o tipo de retorno de um determinado método (por exemplo String.length()) seja intnem sempre significa que seu valor máximo permitido é Integer.MAX_VALUE. Em vez disso, na maioria dos casos, inté escolhido apenas por razões de desempenho. A especificação da linguagem Java diz que números inteiros cujo tamanho é menor que o de intsão convertidos para intantes do cálculo (se minha memória me servir corretamente) e é uma das razões para escolher intquando não há uma razão especial.
O comprimento máximo no tempo de compilação é no máximo 65536. Observe novamente que o comprimento é o número de bytes da representação UTF-8 modificada , não o número de caracteres em um Stringobjeto.
Stringos objetos podem ter muito mais caracteres em tempo de execução. No entanto, se você deseja usar Stringobjetos com DataInpute DataOutputinterfaces, é melhor evitar o uso de Stringobjetos muito longos . Encontrei essa limitação ao implementar os equivalentes Objective-C de DataInput.readUTF()e DataOutput.writeUTF(String).
Como as matrizes devem ser indexadas com números inteiros, o comprimento máximo de uma matriz é Integer.MAX_INT(2 31 -1 ou 2 147 483 647). Isso pressupõe que você tenha memória suficiente para armazenar uma matriz desse tamanho, é claro.
Eu tenho um iMac 2010 com 8 GB de RAM, executando o Eclipse Neon.2 Release (4.6.2) com Java 1.8.0_25. Com o argumento da VM -Xmx6g, executei o seguinte 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());
Isso imprime:
Requested array size exceeds VM limit
1207959550
Portanto, parece que o tamanho máximo da matriz é ~ 1.207.959.549. Então percebi que na verdade não nos importamos se o Java ficar sem memória: estamos apenas procurando o tamanho máximo da matriz (que parece ser uma constante definida em algum lugar). Assim:
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
Então, parece que o máximo é Inteiro.MAX_VALUE - 2 ou (2 ^ 31) - 3
PS: Não sei por que meu StringBuilderlimite máximo foi atingido 1207959550enquanto meu char[]limite máximo atingido (2 ^ 31) -3. Parece que AbstractStringBuilderdobra o tamanho de seu interno char[]para cultivá-lo, o que provavelmente causa o problema.
String é considerada como matriz de char internamente, portanto, a indexação é feita dentro do intervalo máximo. Isso significa que não podemos indexar o membro 2147483648. Portanto, o comprimento máximo de String em java é 2147483647.
O tipo de dados primitivo int é de 4 bytes (32 bits) em java. Como 1 bit (MSB) é usado como um bit de sinal , o intervalo é restrito dentro de -2 ^ 31 a 2 ^ 31-1 (-2147483648 a 2147483647). Não podemos usar valores negativos para indexação. Portanto, obviamente, o intervalo que podemos usar é 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);}}...}
Mas quando o mapeamento de ponto de código> 1byte, ele chama o encodeUTF8método:
Nesse sentido, o comprimento máximo da string é 65535 bytes, ou seja, o comprimento da codificação utf-8. e não charconte
Você pode encontrar o intervalo de ponto de código Unicode modificado da JVM, no link struct utf8 acima.
String
é teoricamenteInteger.MAX_VALUE
, o comprimento de uma string literal na origem parece estar limitado a apenas 65535 bytes de dados UTF-8.Respostas:
Considerando que o método da
String
classelength
retorna umint
, o comprimento máximo que seria retornado pelo método seriaInteger.MAX_VALUE
, que é2^31 - 1
(ou aproximadamente 2 bilhões).Em termos de tamanho e indexação de matrizes (como
char[]
provavelmente a maneira como a representação de dados interna é implementada paraString
s), o Capítulo 10: Matrizes da especificação da linguagem Java, o Java SE 7 Edition diz o seguinte:Além disso, a indexação deve ser por
int
valores, conforme mencionado na Seção 10.4 :Portanto, parece que o limite é realmente
2^31 - 1
, pois esse é o valor máximo para umint
valor não negativo .No entanto, provavelmente haverá outras limitações, como o tamanho máximo alocável para uma matriz.
fonte
javac
dá um erro sobre esse ser literal muito longo:javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
javac
paraString
literais (nãoString
objetos), já que não consigo encontrar nenhuma referência aos limites de tamanho paraString
literais na Java Language Specification e na JVM Specification. Tentei criar umString
literal com mais de 100.000 caracteres e o compilador Eclipse não teve problemas ao compilá-lo. (E, correndo o programa foi capaz de mostrar que o literal teve umaString.length
maior do que 100.000.)java.io.DataInput.readUTF()
ejava.io.DataOutput.writeUTF(String)
diga que umString
objeto é representado por dois bytes de informações de comprimento e pela representação UTF-8 modificada de cada caractere na sequência. Isso conclui que o comprimento da String é limitado pelo número de bytes da representação UTF-8 modificada da string quando usada comDataInput
eDataOutput
.Além disso, a especificação
CONSTANT_Utf8_info
encontrada na especificação da máquina virtual Java define a estrutura da seguinte maneira.Você pode achar que o tamanho do 'comprimento' é de dois bytes .
Que o tipo de retorno de um determinado método (por exemplo
String.length()
) sejaint
nem sempre significa que seu valor máximo permitido éInteger.MAX_VALUE
. Em vez disso, na maioria dos casos,int
é escolhido apenas por razões de desempenho. A especificação da linguagem Java diz que números inteiros cujo tamanho é menor que o deint
são convertidos paraint
antes do cálculo (se minha memória me servir corretamente) e é uma das razões para escolherint
quando não há uma razão especial.O comprimento máximo no tempo de compilação é no máximo 65536. Observe novamente que o comprimento é o número de bytes da representação UTF-8 modificada , não o número de caracteres em um
String
objeto.String
os objetos podem ter muito mais caracteres em tempo de execução. No entanto, se você deseja usarString
objetos comDataInput
eDataOutput
interfaces, é melhor evitar o uso deString
objetos muito longos . Encontrei essa limitação ao implementar os equivalentes Objective-C deDataInput.readUTF()
eDataOutput.writeUTF(String)
.fonte
Como as matrizes devem ser indexadas com números inteiros, o comprimento máximo de uma matriz é
Integer.MAX_INT
(2 31 -1 ou 2 147 483 647). Isso pressupõe que você tenha memória suficiente para armazenar uma matriz desse tamanho, é claro.fonte
Eu tenho um iMac 2010 com 8 GB de RAM, executando o Eclipse Neon.2 Release (4.6.2) com Java 1.8.0_25. Com o argumento da VM -Xmx6g, executei o seguinte código:
Isso imprime:
Portanto, parece que o tamanho máximo da matriz é ~ 1.207.959.549. Então percebi que na verdade não nos importamos se o Java ficar sem memória: estamos apenas procurando o tamanho máximo da matriz (que parece ser uma constante definida em algum lugar). Assim:
Que imprime:
Então, parece que o máximo é Inteiro.MAX_VALUE - 2 ou (2 ^ 31) - 3
PS: Não sei por que meu
StringBuilder
limite máximo foi atingido1207959550
enquanto meuchar[]
limite máximo atingido (2 ^ 31) -3. Parece queAbstractStringBuilder
dobra o tamanho de seu internochar[]
para cultivá-lo, o que provavelmente causa o problema.fonte
aparentemente está vinculado a um int, que é 0x7FFFFFFF (2147483647).
fonte
O tipo Return do método length () da classe String é int .
Consulte http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()
Portanto, o valor máximo de int é 2147483647 .
String é considerada como matriz de char internamente, portanto, a indexação é feita dentro do intervalo máximo. Isso significa que não podemos indexar o membro 2147483648. Portanto, o comprimento máximo de String em java é 2147483647.
O tipo de dados primitivo int é de 4 bytes (32 bits) em java. Como 1 bit (MSB) é usado como um bit de sinal , o intervalo é restrito dentro de -2 ^ 31 a 2 ^ 31-1 (-2147483648 a 2147483647). Não podemos usar valores negativos para indexação. Portanto, obviamente, o intervalo que podemos usar é de 0 a 2147483647.
fonte
Como mencionado na resposta de Takahiko Kawasaki , java representa seqüências de caracteres Unicode na forma de UTF-8 modificado e na estrutura CONSTANT_UTF8_info da JVM-Spec , 2 bytes são alocados no comprimento (e não no número de caracteres de String).
Para estender a resposta, o método da biblioteca ASM jvm bytecode contém:
putUTF8
Mas quando o mapeamento de ponto de código> 1byte, ele chama o
encodeUTF8
método:Nesse sentido, o comprimento máximo da string é 65535 bytes, ou seja, o comprimento da codificação utf-8. e não
char
conteVocê pode encontrar o intervalo de ponto de código Unicode modificado da JVM, no link struct utf8 acima.
fonte