Java String

sith-call.dev·2023년 4월 20일
0

Java

목록 보기
6/6

Java String 더하기

class AddString{
	String concatMethod(String s1, String s2){
    	return s1.concat(s2)
    }
    String addOperationMethod(String s1, String s2){
    	return s1 + s2;
    }
    String stringBuilderMethod(String s1, String s2){
    	StringBuilder sb = new StringBuilder();
        sb.append(s1);
        sb.append(s2);
        return sb.toString();
    }
    String stringBufferMethod(String s1, String s2){
    	StringBuffer sbr = new StringBuffer();
        sbr.append(s1);
        sbr.append(s2);
        return sbr.toString();
    }
}

String의 특성

String Constance Pool VS Heap Memory By JVM

class StringMethod{
	@Test
	void test1(){
    	String heapString = new String("Test String");
        String constantPoolString1 = "Test String";
        String constantPoolString2 = "Test String";
        assertThat(constantPoolString1).isSameAs(constantPoolString2); // True
        assertThat(heapString).isSameAs(constantPoolString1); // False
    }
    @Test
	void test2(){
    	String heapString = new String("String in heap memory.");
        String heapStringMovedtoConstancePool = heapString.intern();
        assertThat(heapString).isSameAs(heapStringMovedtoConstancePool); // True
    }
}
  1. Java에서 String은 위와 같이 두 개의 메모리 영역에 할당된다. 하나는 Java Heap 메모리 영역이고, 하나는 String Constanct Pool이란 영역이다.
  2. 큰 따옴표로 이용하여 선언한 String 같은 경우에는 String Constant Pool에 할당되어 재사용이 가능해진다. new 연산자로 선언한 String은 Java Heap Memory에 할당되어 immutable한 속성을 그대로 가져간다.
  3. 따라서 재사용이 자주 발생되는 String은 큰 따옴표로 선언해서 사용해야 한다.

intern() 메소드

만약에 어떤 String이 Constant Pool에 없을 경우에 이를 Constant Pool에 넣고 그것의 참조를 반환한다.
따라서 위의 코드에서 아래와 같은 관계가 형성된다.

  • heapStringMovedtoConstancePool 참조 == heapString 참조

StringBuilder와 StringBuffer

공통점 - mutable하게 String 사용하기

StringBuilder와 StringBuffer는 mutable한 객체이다. 따라서 수정을 하더라도 새로 객체를 생성하는 것이 아니라, 해당 데이터 자체를 바로 수정한다. 즉, 수정 시에 오버헤드가 발생하지 않는다.
그래서 String을 수정할려고 할 때 이를 mutable하게 수정할 수 있도록 도와주는 객체이다.

차이점 - thread safe

StringBuilder는 thread safe하지 않지만, StringBuffer는 thread safe하다. 이때 thread safe란 동시성과 관련된 용어이다. 즉, 여러 개의 thread가 해당 StringBuffer에 접속한다고 하여도 동시성이 보장된다는 것이다.

Thread Safe 구현방법

  1. Re-entrancy
    어떤 함수가 한 스레드에 의해 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 올바로 주어져야 한다.

  2. Thread-local storage
    공유 자원의 사용을 최대한 줄여 각각의 스레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는다.
    이 방식은 동기화 방법과 관련되어 있고, 또한 공유상태를 피할 수 없을 때 사용하는 방식이다.

  3. Mutual exclusion
    공유 자원을 꼭 사용해야 할 경우 해당 자원의 접근을 세마포어 등의 락으로 통제한다.

  4. Atomic operations
    공유 자원에 접근할 때 원자 연산을 이용하거나 '원자적'으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현할 수 있다.

Mutex와 Semaphore

  • Mutex : 하나의 프로세스 또는 쓰레드만 임계 영역에 접근할 수 있도록 함
  • Semaphore : 설정된 수만큼의 프로세스 또는 쓰레드만 임계 영역에 접근할 수 있도록 함

Java Compiler의 String 최적화

위와 같이 mutable과 관련해서 java compiler가 최적화를 시켜준다.
즉, 그냥 상수로만 String을 사용한다고 하더라도, 메모리 낭비가 안되도록 알아서 컴파일 해준다는 뜻이다.

  • 원래 소스 코드
class solution{
	void test(){
    	String str = "a" + "b";
    }
}
  • 1.5 버전으로 컴파일한 소스 코드를 리버싱한 코드
class solution{
	void test(){
    	String str = StringBuilder.append("a").append("b").toString();
    }
}

결론적으로는 딱히 신경 쓰지 않아도 될 듯 하다. 1.5 버전 이후에서도 계속해서 최적화 성능은 올라간 듯 하다.

참고 문헌

  1. https://gist.github.com/benelog/b81b4434fb8f2220cd0e900be1634753
  2. https://jwprogramming.tistory.com/13#recentComments
  3. https://worthpreading.tistory.com/90
  4. https://junghn.tistory.com/entry/JAVA-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B6%99%EC%9D%B4%EB%8A%94-%EB%B0%A9%EB%B2%95concat-StringBuilder-StringBuffer
profile
Try again, Fail again, Fail better

0개의 댓글