Skills/Java

Java - String pool과 불변

aoaa 2022. 12. 12. 16:06

Java에서 String은 불변(Immutable) 객체입니다.

 이 불변 객체는 객체가 생성된 후 내부의 상태가 변하지 않고 계속 유지되는 객체로, 변수에 객체가 한 번 할당되면 해당 객체의 참조를 변경할 수도, 내부의 상태를 수정할 수도 없는 것입니다.

 이를 immutable, '불변성'이라고 하는데, String을 불변 객체로 만든 이유에 대해 알아보겠습니다.


1. String Pool

 Java에서는 String Pool이라는 공간에 String을 포함시켜 매번 String 객체를 새로 생성하기보다 값이 같은 String이라면 String Pool에 있는 객체를 재사용할 수 있도록 구현했습니다.

 

이는 값이 같은 String은 String Pool 내에서 String 객체를 공유하도록 한 것이다. 이 때, 객체 공유 시, String은 반드시 immutable, 해야하는데 이유를 살펴보면

String s1 = "Java"; 
String s2 = "Java"; 

 s1과 s2는, "Java"라는 value를 갖는 String Pool 내부의 하나의 String 객체를 바라보고 있습니다. 이 때 s1의 값을 "Python"으로 바꾼다면 s1은 String Pool 내부의 다른 String 객체를 바라보게 됩니다.

 

 이 때 String이 mutable하다면,  s1의 값만 "Python"으로 바꿀 수 있고 s2는 그대로 "Java"로 남아있게 되는 데, 값이 다른지만 같은 참조를 가진다는 것은 앞뒤가 맞지 않습니다.


2. 보안

 사용자의 이름이나 패스워드, 혹은 네트워크 연결을 위한 포트 번호나 connection URL, 파일 이름 등 중요한 정보를 String으로 받을 때가 많습니다. 이는 JVM의 class loader가 class loading을 수행할 때도 마찬가지인데

void criticalMethod(String userName) {
    // perform security checks
    if (!isAlphaNumeric(userName)) {
        throw new SecurityException(); 
    }

    // do some secondary tasks
    initializeDatabase();

    // critical task
    connection.executeUpdate("UPDATE Customers SET Status = 'Active' " +
      " WHERE UserName = '" + userName + "'");
}

 

 String이 mutable하다면, 메서드의 인자로 받은 값은 메서드의 caller(호출자)에 의해 언제든지 바뀔 수 있게 되어, 이는 보안상 엄청난 취약점을 발생시킵니다.

 

 


3. 동기화 (Synchronization)

 객체가 불변이면 멀티 스레드 환경에서도 값이 바뀔 위험이 없기 때문에, 자연스럽게 thread-safe하고, 동기화와 관련된 위험 요소에서 벗어날 수 있으며, 여러 스레드에서 동시에 접근해도 별다른 문제가 없을 것입니다.

 

또한 String의 경우 한 스레드에서 값을 바꾸면, 해당 객체의 값을 수정하는 것이 아니라 새로운 객체를 String Pool에 생성한다. 따라서 thread-safe하다고 볼 수 있다.


4. Hashcode Caching

 String의 hashCode() API를 보면, hash의 값을 계산한 적이 없을 때 최초 1번만 실제 계산 로직을 수행하고, 이후부터는 이전에 계산했던 값을 그냥 리턴만 하도록 되어 있다. 즉 hashCode 값을 캐싱(caching)하고 있습니다.

 Hash 자료구조의 구현체, 예를 들면 HashMap, HashTable, HashSet와 같은 클래스에서 꽤 자주 호출되는데, String 객체와 함께 Hash 구현체를 사용하는 경우라면 이러한 caching 덕분에 성능상 큰 이점을 볼 수 있을 것입니다.


5. 성능

 무엇보다 String이 불변성을 가짐으로써 "성능"이라는 측면에서 유리하다는 것을 알 수 있다. String은 상대적으로 자주 쓰이는 타입이기 때문에, String의 성능을 개선하는 것은 전체 애플리케이션의 성능에도 긍정적인 영향을 주게 됩니다.

 

 

 

 

 

 

 

 

참조