Java에서 문자열의 최대 길이-length () 메소드 호출


150

에서 자바 하는 최대 크기 무엇 String받는 참조 객체가 가질 수있는 length()메서드 호출?

나는 length()크기 를 반환 알고String 로 있다 char [].


5
a의 길이 String는 이론적으로 Integer.MAX_VALUE이지만 소스의 문자열 리터럴 길이는 65535 바이트 의 UTF-8 데이터 로만 제한되는 것으로 보입니다 .
200_success

답변:


169

String클래스의 length메소드가를 반환한다는 것을 고려하면 int, 메소드가 반환하는 최대 길이 Integer.MAX_VALUE2^31 - 1약 20 억입니다.

(예 : 길이와 배열의 색인의 관점에서 char[]아마도 내부 데이터 표현이 구현되는 방식 인 String들), 제 10 장 : 배열Java 언어 사양, 자바 SE 7 Edition은 다음을 말한다 :

배열에 포함 된 변수에는 이름이 없습니다. 대신 음이 아닌 정수 인덱스 값을 사용하는 배열 액세스 표현식에 의해 참조됩니다. 이러한 변수를 배열 의 구성 요소 라고합니다 . 배열에 n구성 요소 n가있는 경우 배열 의 길이 입니다. 배열의 구성 요소는에서 0까지의 정수 색인을 사용하여 참조됩니다 n - 1.

또한 10.4 절int 에서 언급 한 바와 같이 인덱싱은 값을 기준으로 해야합니다 .

배열은 int값 으로 색인화해야 합니다.

따라서 2^31 - 1음수가 아닌 최대 값이므로 한계가 실제로 나타납니다.int 값 .

그러나 배열의 할당 가능한 최대 크기와 같은 다른 제한 사항이있을 수 있습니다.


26
Integer.MAX_VALUE는 실제로 2 ^ 31-1입니다. :)
Michael Myers

1
큰 대답 남자! String.java 소스 코드를 살펴 보았습니다. 그렇습니다 .'count '는 char 배열의 길이를 반환하는 int 변수이며 char 배열은'value '변수에 저장됩니다 (char []). 문자열 크기는 약 2GB가 될 수 있습니다. 물론 이러한 메모리 크기를 할당하는 데 제한이있을 수 있습니다. 감사!
타이치

5
방금 65546보다 긴 hello world java 프로그램에서 문자열 리터럴을 정의하려고했습니다. javac해당 리터럴이 너무 길다는 오류가 발생합니다.javac HelloWorld.java 2>&1|head -c 80 HelloWorld.java:3: constant string too long
dlamblin

2
@ dlamblin : Java 언어 사양 및 JVM 사양에서 리터럴에 대한 크기 제한에 대한 참조를 찾을 수 없으므로 리터럴 ( 객체 아님) 에 javac대한 제한처럼 들립니다 . 100,000 자보다 큰 리터럴을 만들려고 시도했지만 Eclipse 컴파일러에서 컴파일하는 데 문제가 없었습니다. (그리고 프로그램을 실행하면 리터럴이 100,000보다 큼을 보여줄 수있었습니다 .)String StringStringStringString.length
coobird

3
@Premraj 3 년 전 이었으므로 생각해야했습니다. ;) 내가 의미 한 것은; 최대 크기의 문자열을 만들려면 어쨌든 많은 메모리가 필요합니다. 문자 당 2 바이트 ~ 4GB가 필요하지만 StringBuilder 또는 char []에서이를 빌드해야합니다. 즉, 문자를 생성하기 위해 문자 당 다른 2 바이트가 필요합니다. 즉, 최소 ~ 4GB (적어도 일시적으로)
Peter Lawrey

25

java.io.DataInput.readUTF()java.io.DataOutput.writeUTF(String)있다고 String객체에 의해 표현되는 두 바이트 길이의 정보의 수정 UTF-8 스트링 내의 각 문자의 표현. 이는 String의 길이가 DataInputand 와 함께 사용될 때 문자열의 수정 된 UTF-8 표현의 바이트 수에 의해 제한된다는 결론을 내립니다 DataOutput.

또한, 의 사양CONSTANT_Utf8_info 은 다음과 같이 자바 가상 머신 스펙은 검색된 구조를 정의한다.

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}

'length'의 크기가 2 바이트 임을 알 수 있습니다 .

특정 방법 (예를 들면의 리턴 타입 그건 String.length())이다는 int항상 허용되는 최대 값입니다 의미하지 않는다 Integer.MAX_VALUE. 대신 대부분의 경우 int성능상의 이유로 선택됩니다. Java 언어 사양에 따르면 크기가 정수보다 작은 정수는 계산 전에 int변환됩니다 int(메모리가 올바르게 제공 int되는 경우) 특별한 이유가없는 경우 선택 해야하는 이유 중 하나 입니다.

컴파일 타임의 최대 길이는 최대 65536입니다. 길이는 오브젝트 의 문자 수가 아니라 수정 된 UTF-8 표현 의 바이트 수입니다 String.

String객체는 런타임에 훨씬 더 많은 문자를 가질 수 있습니다. 사용할 경우, String와 객체 DataInputDataOutput인터페이스를 너무 오래 사용하지 않는 것이 좋습니다 String객체. 이 I-C의 목표 등가물을 구현할 때이 제한을 발견 DataInput.readUTF()하고 DataOutput.writeUTF(String).


1
이것이 기본 답변이어야합니다.
Nick

20

배열은 정수로 색인화해야하므로 배열의 최대 길이는 Integer.MAX_INT(2 31 -1 또는 2 147 483 647)입니다. 이것은 물론 해당 크기의 배열을 보유하기에 충분한 메모리가 있다고 가정합니다.


9

Java 1.8.0_25와 함께 Eclipse Neon.2 릴리스 (4.6.2)를 실행하는 8GB RAM의 2010 iMac이 있습니다. VM 인수 -Xmx6g를 사용하여 다음 코드를 실행했습니다.

StringBuilder sb = new StringBuilder();
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());

인쇄합니다 :

Requested array size exceeds VM limit
1207959550

따라서 최대 배열 크기는 ~ 1,207,959,549 인 것으로 보입니다. 그런 다음 Java에 메모리가 부족한 경우 실제로 신경 쓰지 않는다는 것을 깨달았습니다. 우리는 최대 배열 크기를 찾고 있습니다 (어딘가에 일정하게 정의 된 것처럼 보입니다). 그래서:

for (int i = 0; i < 1_000; i++) {
    try {
        char[] array = new char[Integer.MAX_VALUE - i];
        Arrays.fill(array, 'a');
        String string = new String(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);
    }
}

어떤 지문 :

Requested array size exceeds VM limit
Last: 2147483647
Last: 0
Requested array size exceeds VM limit
Last: 2147483646
Last: 1
Java heap space
Last: 2147483645
Last: 2

따라서 최대 값은 정수인 것 같습니다 .MAX_VALUE-2 또는 (2 ^ 31)-3

PS 잘 모르겠어요 왜 내 StringBuilder에서 끝나가는 밖으로 1207959550내 동안 char[](2 ^ 31)에 끝나가 -3입니다. AbstractStringBuilder내부 크기 가 두 배로 char[]커져서 문제가되는 것 같습니다.


1
매우 유용한 실질적인 문제 처리
Pavlo Maistrenko

5

분명히 그것은 0x7FFFFFFF (2147483647) 인 int에 바인딩되어 있습니다.


4

String 클래스의 length () 메소드의 리턴 유형은 int 입니다.

공개 int 길이 ()

보내다 http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length ()를 하십시오.

따라서 int의 최대 값은 2147483647 입니다.

문자열은 내부적으로 char 배열로 간주되므로 인덱싱은 최대 범위 내에서 수행됩니다. 이것은 우리가 2147483648 번째 멤버를 인덱스 할 수 없다는 것을 의미합니다. 따라서 자바에서 String의 최대 길이는 2147483647입니다.

기본 데이터 유형 int는 java에서 4 바이트 (32 비트)입니다. 1 비트 (MSB)가 부호 비트로 사용되므로 범위는 -2 ^ 31에서 2 ^ 31-1 (-2147483648에서 2147483647)로 제한됩니다. 인덱싱에 음수 값을 사용할 수 없으므로 사용할 수있는 범위는 0에서 2147483647 사이입니다.


0

Takahiko Kawasaki의 답변 에서 언급했듯이 java는 수정 된 UTF-8 형식의 유니 코드 문자열을 나타내며 JVM 사양 CONSTANT_UTF8_info Structure 에서 2 바이트는 길이에 할당되며 문자열의 문자 수는 아닙니다.
답을 확장하기 위해 ASM jvm 바이트 코드 라이브러리의 putUTF8메소드 에는 다음이 포함됩니다.

public ByteVector putUTF8(final String stringValue) {
    int charLength = stringValue.length();
    if (charLength > 65535) {   
   // If no. of characters> 65535, than however UTF-8 encoded length, wont fit in 2 bytes.
      throw new IllegalArgumentException("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);
      }
    }
    ...
}

그러나 코드 포인트 매핑이 1 바이트를 초과하면 encodeUTF8메서드를 호출 합니다.

final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength /*= 65535 */) {
    int charLength = stringValue.length();
    int byteLength = offset;
    for (int i = offset; i < charLength; ++i) {
      char charValue = stringValue.charAt(i);
      if (charValue >= 0x0001 && charValue <= 0x007F) {
        byteLength++;
      } else if (charValue <= 0x07FF) {
        byteLength += 2;
      } else {
        byteLength += 3;
      }
    }
   ...
}

이러한 의미에서 최대 문자열 길이는 65535 바이트, 즉 utf-8 인코딩 길이입니다. 하지 char카운트
당신은 위의 UTF8 구조체 링크에서, JVM의 수정 된 유니 코드 코드 포인트 범위를 찾을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.