일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- springboot
- devops
- jenkins
- redis
- elasticsearch
- AWS
- javascript
- Web Server
- 맛집
- Gradle
- db
- ubuntu
- jsp
- IntelliJ
- Git
- JVM
- Spring Batch
- tool
- php
- MySQL
- laravel
- Design Patterns
- it
- Oracle
- java
- Spring
- Spring Boot
- 요리
- ReactJS
- linux
Archives
- Today
- Total
아무거나
Java 메모리(with. JVM) 관련 정리 본문
반응형
최근에 JVM 관련 대화를 나누던 도중 메모리 영역에 대한 잘못된 설명을 해버린적이 있다. 반성하는겸 다시 정리하고자 해당 포스팅을 작성하게 된다.
Java 메모리(with. JVM)
- 정의
- Stack: 정적 할당된 메모리 영역
- boolean, char, short, int, long, float, double.. 등과 같은 데이터 즉, 원시타입의 데이터가 값이랑 같이 Stack 에 할당된다.
- Heap 영역에서 Object 타입 데이터의 참조값이 Stack 에 할당된다.
- Stack 의 메모리는 Thread 당 하나씩만 할당된다. 즉, 새로운 Thread 생성시 그 해당 Thread 에 대한 Stack 이 또 새롭게 생성된며 각 Thread 끼리는 Stack 영역을 접근 할 수 없다.
- 간단한 사용예시
public class Test { public void getTest() { int num = 0; } }
- Heap: 동적으로 할당된 메모리 영역
- 계속 사용하니 생명주기가 길다.
- 여러 개의 Thread 가 있어도 Heap 에는 단 하나의 영역만 존재한다.
- Heap 에 생성된 객체 데이터를 참조하는 주소는 Stack 메모리에 생성된다.
- 간단한 사용예시
public class TestObj{} public class Test { public static void main(String[] args) { TestObj testObj = new TestObj(); } }
- Static: 단어 뜻 그대로 정적 메모리이며 컴파일 시간 동안 할당된 메모리이고 고정된 공간을 차지하므로 런타임 중에는 변경할 수 없는 특징을 가지고 있다. 주로 Singleton 과 같은 방식으로 잘 사용한다면 메모리 사용에 대한 이점을 볼 수 있지만 정적 메모리는 공유되는 자원으로써 멀티 쓰레드 환경에서 동시성을 보장하지않으므로 데이터 무결성과 정합성이 지켜지지 않을 수 있기 때문에 주의하자!
- 메모리의 데이터 영역에 변수가 저장 (데이터 영역은 프로그램의 시작과 함께 할당되며, 프로그램이 종료하면 소멸)
- 간단한 사용예시
public class Test { static int num; }
- Stack: 정적 할당된 메모리 영역
- 코드
- Example1
- Example2
// 상기 개념대로면 해당 출력이 "hello world Hi Hi" 로 되어야 되는데 실제 결과는 "hello world Hi" 이다. 왜 그런지 하기 코드를 통해 알아보자. public class Test { public static void main(String[] args) { // Stack 에 title 이라는 변수만 올라가고 실제 String 값은 Heap 영역에 올라가있고 여기서 참조하게 되어있다. String title = "hello world"; System.out.println("Before Title: " + title); // changeTitle 메소드의 파라미터인 String title 의 title 은 stack 에 올라가고 기존에 heap 영역에 생성된 String 값인 hello world 를 복사하고 그 복사된 값을 참조한다. // -> 원래 Example1 에서는 같은 값을 참조하게 되는데 여기서는 복사를 한다. 이유는 String 은 immutable(=변경할 수 없는) 한 클래스이므로 그렇다. (또한 Boolean, Integer, Long 등 과 같은 Wrapper 클래스들은 immutable 한 클래스로 쓰임, 반대인 mutable 한 객체는 List, ArrayList, HashMap 등의 컬렉션들이 대표적인 mutable 한 객체이다.) // -> 만약 문자열을 mutable 하게 사용하려면 StringBuilder 의 append 메소드를 사용하면 된다. // changeTitle 메소드에 s += " Hi"; 을 보면 복사된 값에 더해지는게 아니다. 동작하지 않는 이유는 += 연산자는 그대로 갖다 붙이는게 아니라 새롭게 Heap 영역에 생성된 곳에다가 참조하게 된다. (기존 연결된 참조는 끊긴다.) // 해당 메소드가 끝나면 메소드에서 사용된 Stack 영역에 올라가 있던 변수인 s 는 pop 된다. changeTitle(title); System.out.println("After Title 1: " + title); // 위의 설명대로 += 연산자이므로 새롭게 Heap 영역에 생성된 값을 title 변수에서 참조한다. title += " Hi"; System.out.println("Before Title 2: " + title); } public static void changeTitle(String s) { s += " Hi"; } }
- 여기서 연결이 끊기고 남아있는 객체들은 Garbage 이므로 GC(=Garbage Collector) 에서 제거해준다. (gc 에 대해 자세히 알고 싶으면 https://bkjeon1614.tistory.com/718 참고)
반응형
'Java & Kotlin > Java' 카테고리의 다른 글
Spring Batch 6편 - Chunk-Oriented Processing (0) | 2022.11.06 |
---|---|
Java Stream 이란 (0) | 2022.08.11 |
Garbage Collection (요약정리본) (0) | 2022.07.27 |
Java 의 Optional 개념과 올바르게 사용하는 방법 (0) | 2022.07.22 |
JDBC 동작과정 (0) | 2022.01.07 |
Comments