점프 투 자바를 보면서 스터디를 하면 코딩을 하기 보다는 개념만 많이 보는 느낌이다.

그래서 스터디 방식을 연습문제를 풀면서 코드 위주로 바꾸기로 하였는데,,,,,,,

그 전에 내가 기록하고 싶고 기억해야 할 자바 특징 중 자료형에서의 메모리 관련한 내용을 가져왔다!

Data Type (자료형)?

Data Type (자료형) 이란, 변수에 저장되는 데이터 종류에 따른 형태를 의미하는데 Primitive 타입과 Reference 타입으로 나뉜다.

Data Type Primitive Reference
종류 boolean, char, byte, short, int, long, float, double array, enum, class, interface
특징 Literal 객체 타입
저장 영역 Stack Heap
메모리 크기 boolean(1byte), char(2byte), byte(1byte), short(2byte), int(4byte), long(8byte), float(4byte), double(8byte) 4byte (객체의 주소 값)

Primitive Type (원시 자료형)

Primitive 타입은 비객체 타입이라 new 키워드로 객체를 생성하여 사용할 수 없고 literal로만 값을 세팅할 수 있다. 또한 null 값도 가질 수 없다

💡 Literal 이란, String a = “gain”; 또는 int i =1;과 같이 객체 생성없이 고정된 값을 그대로 대입하는 방법을 말한다. 인턴 풀에 저장하고 동일한 문자열이 선언되면 캐시된 문자열을 리턴한다.

하지만 객체 취급이 필요할 땐 Wrapper 클래스로 변환하여 해당 값을 객체로 만들어 줄 수 있다. 다만 산술 연산을 위해 정의된 클래스가 아니므로, 인스턴스에 저장된 값은 변경하지 못하고 참조만 가능하다!

String / StringBuffer / StringBuilder

String / StringBuffer / StringBuilder는 Reference Type (참조) 자료형이다.

  • String
    • String 자료형에서 파라미터는 Stack 영역에 생성되고 실제 값은 Heap 영역에 메모리 주소를 참조하여 생성된다.
    • String은 한번 생성되면 문자열이 변경되지 않는 immutable(불변) 성질을 가지고 있다.

      그래서 새로운 문자열을 추가할 시에 또 다른 String 객체를 생성하는 것이므로 메모리 주소 값이 달라 진다.

  • StringBuffer / StringBuilder
    • StringBuffer 또는 StringBuilder는 mutable(변경 가능)하다.

      String인 경우엔 문자열이 합쳐질 때마다 다른 메모리 주소를 가지게 되지만(이전 메모리 주소는 GC에 의해 제거될 수 있음) StringBuffer나 StringBuilder의 경우에는 하나의 메모리 주소 안에서 문자열이 추가된다.

    • StringBuffer는 동기화를 지원하며 멀티쓰레드 환경에서 안전하고 StringBuilder는 동기화 지원을 하지 않으며 단일쓰레드로 돌아가기 때문에 성능이 우수하고 빠르다는 장점이 있다.

메모리 주소 공유에 대한 실습을 진행하려고 한다!

  • String

      public class StMem {
          public static void main(String[] args){
              String st = new String("Hi");
              System.out.println(st+" "+System.identityHashCode(st));
              st += " ";
              System.out.println(st+" "+System.identityHashCode(st));
              st += "ST!";
              System.out.println(st+" "+System.identityHashCode(st));
          }
      }
    
    • st 객체에 “Hi” + “ ``“ + “ST!” 를 입력했다.
    • 문자열을 추가할 때마다 각각 어떤 메모리 주소 값을 갖는지 출력해 보았다.
      Hi 705927765
      Hi  366712642
      Hi ST! 1829164700
    

    String 자료형은 문자열이 추가될 때마다 각각 다른 메모리 주소 값을 갖는다!

  • StringBuffer

      public class SbMem {
              public static void main(String[] args){
              StringBuffer sb = new StringBuffer("Hello");
              System.out.println(sb+" "+System.identityHashCode(sb));
              sb.append(" ");
              System.out.println(sb+" "+System.identityHashCode(sb));
              sb.append("SB!");
              System.out.println(sb+" "+System.identityHashCode(sb));
          }
      }
    
    • sb 객체에 “Hello” + “ ``“ + “SB!” 를 입력했다.
    • 문자열을 추가할 때마다 각각 어떤 메모리 주소 값을 갖는지 출력해 보았다.
      Hello 705927765
      Hello  705927765
      Hello SB! 705927765
    

    StringBuffer 자료형은 문자열이 추가되어도 동일한 메모리 주소 값을 갖는다!

    StringBuild도 동일하다 😀

그래서 업무 관련 주목 포인트는?

최근에 작업한 시스템 중에 거의 모든 메소드를 static으로 선언한 경우가 있었다. 이는 Garbage Collector의 관여가 없기 때문에 메모리 부족 현상이 발생했었다.

이 때 자바 메모리 구조를 알아야 하는 필요성을 아주아주~~~ 잘! 느꼈다!

그래서 이번에도 기억해야 할 것은!

  • new 키워드로 생성한 객체는 Heap 영역에 생성된다. 그래서 GC가 자주 사용하지 않는 메모리 영역을 주기적으로 제거해 준다!

    파라미터는 Stack 영역에 생성되고 메모리만 Heap 영역에 생기는 건데 메모리 주소는 공유되지 않는다!

  • Data Type(자료형) 중에서 Primitive Type은 Stack 영역에 생성된다. Stack 영역은 쓰레드 별로 한 개씩 생성되지만 Static과 Heap 영역을 공유하여 사용할 수 있다. (Static 영역에서 Heap영역의 메모리 주소를 참조한다!)
  • String은 메모리 주소를 공유하지 않고, StringBuffer나 StringBuilder는 메모리 주소를 공유하기 때문에 String보다 메모리 사용량도 많고 속도도 느리다!

Leave a comment