[Java] 내가 기억할 자바 1 - 자료형에서의 메모리
점프 투 자바를 보면서 스터디를 하면 코딩을 하기 보다는 개념만 많이 보는 느낌이다.
그래서 스터디 방식을 연습문제를 풀면서 코드 위주로 바꾸기로 하였는데,,,,,,,
그 전에 내가 기록하고 싶고 기억해야 할 자바 특징 중 자료형에서의 메모리 관련한 내용을 가져왔다!
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 자료형은 문자열이 추가될 때마다 각각 다른 메모리 주소 값을 갖는다!
- st 객체에 “
-
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도 동일하다 😀
- sb 객체에 “
그래서 업무 관련 주목 포인트는?
최근에 작업한 시스템 중에 거의 모든 메소드를 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