본문 바로가기
💊 Java/- Java Lang

[조금 더 깊은 Java] String 과 String Constant Pool

by Wonit 2021. 11. 23.

 

우리는 Java 를 사용하면서 아주 많은 String 의 Literal 을 이용하게 된다.

 

오늘은 그 String이 어떤 특성을 가졌는지 조금 다른 각도에서 봐보려 한다.

 

String 은?

 

String 은 Java 에서 제공하는 특별한 자료형이다.

 

우리는 String 을 생성하기 위해서 2가지 방법으로 이용하게 된다.

 

  1. "..." Literal 을 이용하는 방법
  2. new 연산자를 통해 String 객체의 생성자로 value 주입

 

이러한 방법을 이용해서 String 객체를 생성하면, 우리가 일반적으로 생각하는 방법과는 조금 다른 방법으로 문자열 데이터가 저장이 된다.

 

자바에서 모든 String 은 constant 형태로 한 번 생성이 된다면 update 라는 개념이 사라진다.

 

즉, Java 의 String 은 Immutable 이라고 할 수 있다.

 

Immutable 이라는 소리는 결국 값을 수정한다면 새로운 객체를 생성하고 그 값을 재할당해야 하는데, 왜 Java 의 String 은 Immutable 할까?

 

String 이 Java 에서 Immutable 한 이유

 

그 이유로는 여러가지가 있지만 대표적으로는 다음 3가지를 꼽는다.

 

  1. 캐싱
  2. 동기화
  3. 보안성

 

캐싱

아래에서 나오겠지만 JVM이 String Constant Pool 이라는 영역을 만들고 문자열들을 Constant 화 하여 다른 변수 혹은 객체들과 공유하게 되는데, 이 과정에서 데이터 캐싱이 일어나고 그 만큼 성능적 이득을 취할 수 있다.

 

동기화

일단 어떤 데이터든 Immutable 하다면 Multi-Thread 환경에서 동기화 문제가 발생하지 않기 때문에 더욱 safe 한 결과를 낼 수 있다.

 

보안적 이유

여러 자료를 찾아본 결과, String 이 Immutable 한 이유로 Security 를 꼽는데, 그 이유는 다음과 같다.

 

If we don't make the String immutable, it will pose a serious security threat to the application. For example, database usernames, passwords are passed as strings to receive database connections. The socket programming host and port descriptions are also passed as strings. The String is immutable, so its value cannot be changed. If the String doesn't remain immutable, any hacker can cause a security issue in the application by changing the reference value

 

즉, 만약 Mutable 하다면 특정 공격 벡터에 의해서 Integrity 한 데이터가 아니게 될 수 있기 때문이다.

 

String Constant Pool

 

앞서 잠시 String 은 Constant Pool 을 사용한다고 했는데, 조금 더 알아보자.

 

 

String 은 한번 사용이 되면 또다시 재사용될 확률이 높기 때문에 이에 대한 적절한 대처 방법으로 Heap 영역 내에 문자열 상수의 Pool 을 유지하고 해당 Pool 로 사용자가 정의한, 변수가 가지고 있는 value 들을 담게 된다.

 

이 과정에서 String value 들이 Immutable 한 특성을 가지게 되고 Constant Pool 이 있기 때문에 앞서 이야기한 장점들을 얻을 수 있게 된다

 

그럼 모든 String 이 Constant Pool 에서 값을 가져올까?

 

아니다.

 

String Constant Pool 을 이용하기 위해서는 앞서 본 2가지 String 생성 방법 중 Literal을 이용한 방법으로만 가능하다.

 

이를 증명하기 위해 다음 간단한 코드를 확인해보자

 

String a = "AAAA";
String b = "AAAA";

assertTrue(a == b);

// --- new 로 객체 생성

String c = new String("BBBB");
String d = new String("BBBB");

assertFalse(a == b);

 

위의 코드로 알 수 있듯, Literal 로 String 객체를 생성한다면 Constant Pool 에 해당 문자열의 값이 담긴 메모리 주소를 공유하여 다른 String 객체가 동일한 문자열을 사용 가능하고 그 만큼 이득을 취할 수 있게 된다.

 

성능을 위한 고민은?

 

이러한 Constant Pool은 Java 6 이전에 Permenent Generation 에 있어 고정된 메모리 사이즈로 문제가 발생했었었다.

 

하지만 Java 7, 8 ... 을 거쳐오며 Heap Size 를 통해 직접 Constant Pool 을 조절할 수 있도록 Heap 영역에서 관리하도록 하였다.

 

그래서 Constant Pool 의 Heap Size 를 조절하여 더 많은 Constant 를 유지할 수 있도록 할 수 있다.

 

추가적으로 String Constant Pool 은 내부적으로 HashTable 구조를 가지게 된다.

 

각 String Constant 을 hashing 하고 해당 데이터를 key 로 value를 찾기 때문에 기본적으로도 Constant Pool 의 성능은 어느 정도 보장이 되어있다고 한다.

 

게다가 StringTableSize 를 바꿔줄 수도 있어서 이 부분도 고려해볼만 하다.

댓글0