IT story

문자열에“”를 추가하면 왜 메모리가 절약됩니까?

hot-time 2020. 5. 12. 08:02
반응형

문자열에“”를 추가하면 왜 메모리가 절약됩니까?


많은 데이터가있는 변수를 사용했습니다 String data. 이 문자열의 작은 부분을 다음과 같은 방식으로 사용하고 싶었습니다.

this.smallpart = data.substring(12,18);

몇 시간의 디버깅 (메모리 시각화 도구 사용) 후에는 객체 필드 에 하위 문자열 만 포함되어 있지만 객체 필드의 smallpart모든 데이터를 기억 한다는 것을 알았습니다 data.

코드를 다음과 같이 변경했을 때 :

this.smallpart = data.substring(12,18)+""; 

.. 문제가 해결되었습니다! 이제 내 응용 프로그램은 메모리를 거의 사용하지 않습니다!

어떻게 가능합니까? 누구든지 이것을 설명 할 수 있습니까? 작은 부분이 계속 데이터를 참조한다고 생각하지만 왜 그럴까요?

업데이트 : 큰 문자열을 지우려면 어떻게해야합니까? data = new String (data.substring (0,100))이 작동합니까?


다음을 수행하십시오.

data.substring(x, y) + ""

새로운 (더 작은) String 객체를 만들고 substring ()으로 만든 String에 대한 참조를 버려서 가비지 수집을 가능하게합니다.

알아야 할 중요한 것은 기존 문자열 또는 원래 문자열의 기본이되는 문자 배열에 substring()제공 한다는 것입니다 . 따라서 원래 문자열과 동일한 메모리를 사용합니다. 이것은 어떤 상황에서는 유리할 수 있지만, 부분 문자열을 가져 와서 원래 문자열을 처리하려는 경우 문제가됩니다 (발견 한대로).

자세한 정보는 JDK 문자열 소스 substring () 메소드 를보십시오.

편집 : 당신의 메모리 사용량을 줄입니다 문자열에서 새로운 문자열을 구성, 당신의 보충 질문에 대한 답을 제공하는 원래의 문자열에 당신에게 참조를 빈.

참고 (2013 년 1 월). 위의 동작은 Java 7u6에서 변경 되었습니다 . 플라이급 패턴은 더 이상 사용되지 않으며 substring()예상대로 작동합니다.


의 출처를 보면 다음을 substring(int, int)반환 함을 알 수 있습니다.

new String(offset + beginIndex, endIndex - beginIndex, value);

value원본은 어디에 있습니까 char[]? 따라서 새로운 String을 얻지 만 기본 동일char[] 합니다.

당신이 할 때 data.substring() + "", 당신은 새로운 기초를 가진 새로운 문자열을 얻는다 char[].

실제로 유스 케이스는 String(String)생성자 를 사용해야하는 유일한 상황입니다 .

String tiny = new String(huge.substring(12,18));

을 사용할 때 substring실제로 새 문자열을 만들지는 않습니다. 여전히 오프셋과 크기 제한이있는 원래 문자열을 참조합니다.

따라서 원래 문자열을 수집하려면을 사용하거나 새 문자열을 사용하여 새 문자열을 만들어야합니다 new String.


작은 부분이 계속 데이터를 참조한다고 생각하지만 왜 그럴까요?

Java 문자열은 char 배열, 시작 오프셋 및 길이 (및 캐시 된 hashCode)로 구성됩니다. 일부 String 작업 substring()은 원본의 char 배열을 공유하고 단순히 오프셋 및 / 또는 길이 필드가 다른 새 String 객체를 만드는 것과 같습니다 . String의 char 배열은 일단 생성되면 수정되지 않기 때문에 작동합니다.

여러 하위 문자열이 겹치는 부분을 복제하지 않고 동일한 기본 문자열을 참조 할 때 메모리를 절약 할 수 있습니다. 알다시피, 어떤 상황에서는 더 이상 필요하지 않은 데이터를 가비지 수집하지 못하게 할 수 있습니다.

이것을 고치는 "올바른"방법은 new String(String)생성자입니다.

this.smallpart = new String(data.substring(12,18));

BTW의 전반적인 최상의 솔루션은 처음에는 매우 큰 문자열을 사용하지 않고 한 번에 몇 KB 씩 작은 청크로 입력을 처리하는 것을 피하는 것입니다.


Java 문자열에서 문자열은 변경 불가능한 개체이며 문자열이 생성되면 가비지 콜렉터가 정리할 때까지 메모리에 남아 있습니다 (이 정리는 당연한 것으로 간주되지 않습니다).

부분 문자열 메소드를 호출하면 Java는 완전히 새로운 문자열을 만들지 않고 원래 문자열 안에 다양한 문자를 저장합니다.

따라서이 코드로 새 문자열을 만들 때 :

this.smallpart = data.substring(12, 18) + ""; 

빈 문자열로 결과를 연결할 때 실제로 새 문자열을 만들었습니다. 그 이유입니다.


1997 년jwz기록한 대로 :

거대한 문자열이있는 경우 하위 문자열 ()을 꺼내고 하위 문자열을 잡고 더 긴 문자열이 가비지 (즉, 하위 문자열의 수명이 길어짐)가되도록하십시오. 거대한 문자열의 기본 바이트는 절대 가지 않습니다. 떨어져.


요약하면 소수의 큰 문자열에서 많은 하위 문자열을 만들면 다음을 사용하십시오.

   String subtring = string.substring(5,23)

큰 문자열을 저장하기 위해 공간 만 사용하기 때문에 큰 문자열의 손실에서 소수의 작은 문자열을 추출하는 경우

   String substring = new String(string.substring(5,23));

더 이상 필요하지 않을 때 큰 문자열을 재생할 수 있으므로 메모리 사용을 줄입니다.

전화 new String한다는 것은 원래 문자열에 대한 참조가 아니라 실제로 새로운 문자열을 받고 있음을 알려주는 유용한 정보입니다.


먼저 호출 java.lang.String.substring하면 String기본 배열의 상당 부분을 복사하는 대신 오프셋과 길이를 사용 하여 원본에 새 창을 만듭니다 .

substring메소드를 자세히 살펴보면 문자열 생성자를 호출 String(int, int, char[])하고 문자열char[] 을 나타내는 전체 전달하는 것을 알 수 있습니다. 이는 하위 문자열 이 원래 문자열 보다 많은 양의 메모리를 차지함을 의미 합니다 .

좋아, 그러나 왜 + ""그것이없는 것보다 적은 메모리를 요구 하는가 ??

수행 +에하는 strings을 통해 구현되는 StringBuilder.append메소드 호출. AbstractStringBuilder클래스 에서이 메소드의 구현을 arraycopy살펴보면 실제로 필요한 부분 ()과 관련이 substring있음을 알 수 있습니다.

다른 해결 방법 ??

this.smallpart = new String(data.substring(12,18));
this.smallpart = data.substring(12,18).intern();

문자열에 ""를 추가하면 때때로 메모리 절약됩니다.

책 전체를 포함하는 거대한 문자열 (백만 문자)이 있다고 가정 해 봅시다.

그런 다음 책의 챕터를 포함하는 20 개의 문자열을 하위 문자열로 만듭니다.

그런 다음 모든 단락을 포함하는 1000 개의 문자열을 만듭니다.

그런 다음 모든 문장을 포함하는 10,000 개의 문자열을 만듭니다.

그런 다음 모든 단어를 포함하는 100,000 개의 문자열을 만듭니다.

여전히 1,000,000자를 사용합니다. 각 장, 단락, 문장 및 단어에 ""를 추가하면 5,000,000자를 사용합니다.

Of course it's entirely different if you only extract one single word from the whole book, and the whole book could be garbage collected but isn't because that one word holds a reference to it.

And it's again different if you have a one million character string and remove tabs and spaces at both ends, making say 10 calls to create a substring. The way Java works or worked avoids copying a million characters each time. There is compromise, and it's good if you know what the compromises are.

참고URL : https://stackoverflow.com/questions/2147783/why-does-appending-to-a-string-save-memory

반응형