You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
new 연산자를 이용한 생성 방법은 Java Heap 메모리에 적재된다.(GC 대상이 된다)
Stringstr1 = "abc"
리터럴 방식을 이용한 생성 방법은 Java Heap 메모리 내부의 String Pool에 적재된다.(GC 대상이 된다)
Immutable 하다.
멀티 스레드 환경에서 Thread-Safe 하다.
그림 1.
1. String 객체
String 데이터 타입은 기본형이 아니라 객체이다. 따라서 Stack에 값이 바로 저장되지 않고 Heap 영역에 저장되고, 그 주소 값을 참조하는 변수가 Stack에 쌓이게 된다.
이때, Heap에 저장할 때는 Heap 안의 String Pool에 적재된다.
그림 2.
1.1 String Interning
String 객체가 리터럴로 할당된다면 Heap 영역의 String Constants Pool에 저장되어 관리된다.
기본적으로 pool안의 객체는 불변성(Immutability)을 띄며 값을 수정할 수 없고, 같은 값이 선언된다면
같은 객체를 참조하도록 한다.
리터럴로 String 값을 할당하면 JVM은 String Pool에서 같은 값이 있는지 검사한다. 그리고 같은 값이 있다면 새로운 공간 할당 없이 해당 객체를 참조하도록 한다.
이런 방식으로 String Constants Pool에 저장하고 관리하는 것을 String Interning이라고 한다.
Stringhost1 = "bunsung";
Stringhost2 = "bunsung";
위와 같이 리터럴로 host1, host2을 선언할 때 내부적으로 intern() 가 실행된다.
String.intern()은 native 메서드로서 API 명세는 아래와 같다.
intern 메서드 API 명세 내용보기
/*** Returns a canonical representation for the string object.* <p>* A pool of strings, initially empty, is maintained privately by the* class <code>String</code>.* <p>* When the intern method is invoked, if the pool already contains a* string equal to this <code>String</code> object as determined by* the {@link #equals(Object)} method, then the string from the pool is`* returned. Otherwise, this <code>String</code> object is added to the* pool and a reference to this <code>String</code> object is returned.* <p>* It follows that for any two strings <code>s</code> and <code>t</code>,* <code>s.intern() == t.intern()</code> is <code>true</code>* if and only if <code>s.equals(t)</code> is <code>true</code>.* <p>* All literal strings and string-valued constant expressions are* interned. String literals are defined in section 3.10.5 of the* <cite>The Java™ Language Specification</cite>.** @return a string that has the same contents as this string, but is* guaranteed to be from a pool of unique strings.*/publicnativeStringintern();
intern() 는 해당 문자열이 String Constant Pool에 이미 있는 경우에는 그 문자열의 주소값을 반환하고 없다면 새로 할당하고 그 주소값을 반환한다는 의미의 메서드이다.
예제
publicclassTestToString {
publicstaticvoidmain(String[] args) {
Stringhost1 = "bunsung";
Stringhost2 = newString("bunsung");
System.out.println("intern() 사용 전 : " + (host1 == host2));
Stringhost1ToIntern = host2.intern();
System.out.println("intern() 사용 후 : " + (host1 == host1ToIntern));
}
}
그림 1. 을 다시 보게되면 'bunsung' 이라는 문자열이 String Constant Pool에 존재하는지 확인하는 과정에서 문자열이 이미 존재하기 때문에 동일한 주소값이 반환되었고 비교 연산 결과 주소 값이 같게 된 것이다.
1.2 String Interning 메모리 관점에서 정리
자바 언어가 담긴 자바 소스 파일(.java)이 클래스 파일(.class)로 컴파일되고 JVM에 로드(load) 될 때,
JVM은 String Constant Pool에 동일한 문자열(위 코드에서는 'bunsung')이 있는지 확인하고 이미 존재한다면 재사용을 하고 없는 경우에는 새로운 문자열을 만든다.
해당 관점에서 여러 레퍼런스가 같은 문자열 리터럴을 참조하더라도 서로 영향이 없도록 불변(immutable) 해야 하는데 위 같은 구조를 갖고 있기 때문에 Thread-Safe 하며 멀티 스레드 환경에서 공유할 수있다.
1.3 String Constant Pool
String Constant Pool 의 위치는 Java7 부터 Perm 영역에서 Heap 영역으로 옮겨졌다.
Perm 영역이란
펌( PERM : Permanent Generation) 영역은 객체의 생명주기가 영구적일 것으로 생각하는 객체들을 관리한다. 이 영역은 GC대상에서 제외된다. 주로 자바의 Class 객체들이나 문자열에 속한 String 객체들이 위치한다
Perm 영역은 실행 시간(Runtime)에 가변적으로 변경할 수 없는 고정된 사이즈이기 때문에 intern() 의 호출은 저장할 공간이 부족하게 만들 수 있었다.
즉 OOM(Out Of Memory) 문제가 발생할 수 있었다.
Heap 영역으로 변경된 이후에는 상수풀에 들어간 문자열도 GC 대상이 된다.
Java 7버전에서 상수풀의 위치가 Perm 영역(정확히 풀어서 써보면 Permanent Generation)에서 Heap으로 옮겨지고 이후에 Java 8 버전에서는 Perm 영역은 완전히 사라지고 이를 MetaSpace라는 영역이 대신하고 있다.
2. 회고 🧹
2023.03.09 목
몇개월 전 멘토에게 개념적인 부분을 학습하길 바란다며 제안했던 내용을 정리하게 되었다.
메모리적 관점에서 String 연산에 new를 사용하지 말라는 내용은 얕게 알고있었는데 이번 기회를 계기로 보다 더 깊은 내용을 학습하게 되었다.
Discussed in https://github.com/orgs/cs-collections/discussions/112
Originally posted by bunsung92 March 8, 2023
📝 구성
Table of contents generated with markdown-toc
0. 핵심 요약 📚
String Pool
에 적재된다.(GC 대상이 된다)그림 1.
1. String 객체
String 데이터 타입은 기본형이 아니라 객체이다. 따라서 Stack에 값이 바로 저장되지 않고 Heap 영역에 저장되고, 그 주소 값을 참조하는 변수가 Stack에 쌓이게 된다.
이때, Heap에 저장할 때는 Heap 안의
String Pool
에 적재된다.그림 2.
1.1 String Interning
String 객체가 리터럴로 할당된다면 Heap 영역의 String Constants Pool에 저장되어 관리된다.
기본적으로 pool안의 객체는
불변성(Immutability)
을 띄며 값을 수정할 수 없고, 같은 값이 선언된다면같은 객체를 참조하도록 한다.
리터럴로 String 값을 할당하면 JVM은
String Pool
에서 같은 값이 있는지 검사한다. 그리고 같은 값이 있다면 새로운 공간 할당 없이 해당 객체를 참조하도록 한다.위와 같이 리터럴로
host1
,host2
을 선언할 때 내부적으로intern()
가 실행된다.String.intern()
은 native 메서드로서 API 명세는 아래와 같다.intern 메서드 API 명세 내용보기
1.2 String Interning 메모리 관점에서 정리
자바 언어가 담긴 자바 소스 파일(.java)이 클래스 파일(.class)로 컴파일되고 JVM에 로드(load) 될 때,
JVM은 String Constant Pool에 동일한 문자열(위 코드에서는 'bunsung')이 있는지 확인하고 이미 존재한다면 재사용을 하고 없는 경우에는 새로운 문자열을 만든다.
해당 관점에서 여러 레퍼런스가 같은 문자열 리터럴을 참조하더라도 서로 영향이 없도록 불변(immutable) 해야 하는데 위 같은 구조를 갖고 있기 때문에
Thread-Safe
하며 멀티 스레드 환경에서 공유할 수있다.1.3 String Constant Pool
String Constant Pool 의 위치는 Java7 부터 Perm 영역에서 Heap 영역으로 옮겨졌다.
Perm 영역은 실행 시간(Runtime)에 가변적으로 변경할 수 없는 고정된 사이즈이기 때문에
intern()
의 호출은 저장할 공간이 부족하게 만들 수 있었다.즉 OOM(Out Of Memory) 문제가 발생할 수 있었다.
Heap 영역으로 변경된 이후에는 상수풀에 들어간 문자열도 GC 대상이 된다.
Java 7버전에서 상수풀의 위치가 Perm 영역(정확히 풀어서 써보면 Permanent Generation)에서 Heap으로 옮겨지고 이후에 Java 8 버전에서는 Perm 영역은 완전히 사라지고 이를 MetaSpace라는 영역이 대신하고 있다.
2. 회고 🧹
2023.03.09 목
The text was updated successfully, but these errors were encountered: