자바 메모리 구조
- 자바 메모리 구조는 크게 3가지로 나눌 수 있으며 메서드영역 힙영역 스택영역으로 나뉠 수 있다.
- 자바가 실행이 된다면 JVM내부에서 3가지의 메모리 구조로 나뉘어 실행이 된다고 보면 된다.
메서드 영역
- 메서드 영역은 클래스 정보를 보관하는 곳이다. 클래스 정보가 붕어빵 틀이라고 한다.
- 프로그램에 실행되는 공통된 데이터를 관리한다. 그렇기에 프로그램의 모든 영역에 공유가 된다.(아직 잘 이해가 안됨)
- 클래스 정보 : 클래스의 실행코드 바이트코드 필드 메서드 생성자와 같이 모든 실행 코드가 존재한다. 자바가 실행되었을 때 클래스의 정보를 읽고 자바에 올리게 되는데 읽은 정보들을 메서드 영역에 올린다.
- 스태틱 영역 : 스태틱 변수들을 보관한다.
- 런타임 상수 풀 : 리터럴을 여러군대에서 사용하게 되는데 최적화 하기 위해 메서드영역의 상수풀이라는곳에 담아두고 가져와서 쓰는 곳이다.
힙영역
- 실제 붕어빵 틀인 A클래스에서 new를 하여 붕어빵을 생성한다면 생성된 붕어빵은 힙 영역에 인스턴스들이 보관이 된다.
- 정리해서 말자자면 new연산자를 사용한다면 객체가 생성되는 영역이다.
- 배열도 힙 영역에 생성이 되는 영역이며 가비지 컬렉션이 이루어지는 주요 역역이며 더이상 힙영역에서 다른곳에서 참조하지 않는다면 GC가 제거한다.
스택영역
- 메서드를 실행할 때마다 스택영역이 하나씩 쌓이게 된다.
- 메인메서드가 실행이 되고 그 안에서 또 메서드가 실행이 된다면 스택영역에서 메인메서드 그 위해 메서드가 하나씩 쌓이게 된다.
- 자바를 실행할 때 하나의 실행 스택이 생성이 되는데 각 스택 프레임은 지역변수 메서드 호출 정보등을 포함한다.(어떤 메서드인지 어떤 지역변수가 있는지)
- 스택프레임 : 스택 영역에 쌓이는 네모박스가 하나의 스택 프레임이며 하나하나씩 쌓이며 메서드가 호출이 될 때마다 하나씩 쌓이며 메서드 호출이 끝나면 사라진다.
- 스택 영역은 각 쓰레드 별로 하나의 실행 스택이 생성이 된다.
메서드 코드는 메서드 영역에
- 특정 클래스로 생성된 100개의 객체가 힙영역에 보관이 된다. 객체의 내부에는 변수와 메서드를 갖게 되며 같은 클래스에서 생성된 객체라고 하더라도 객체에 때라서 필드값이 달라지게 된다. 하지만 메서드는 공통된 코드를 공유하게 된다.
- 메서드는 전부다 같은 공통 코드를 갖는데 하지만 필드처럼 힙메모리에 생성된 객체에 집어넣으면 상당히 비효율 적이다.
- 메서드는 코드를 공유를 하게 되는데 객체가 생성이 될 때 필드들은 메모리에 할당이 되는데 메서드에 대한 새로운 메모리에 대한 할당은 없다. 메서드는 메서드 영역에서 공통으로 관리되고 실행이 된다.
- 만약 x001.method()라는 코드를 호출하면 메서드를 메서드 영역에서 불러 온다음 호출하게 된다. 메서드 영역에는 클래스 정보가 담긴 실행코드가 존재하게 되는데 여기서 불러오게 된다.
정리 : 객체의 메서드를 호출하면 실제로는 메서드 영역에 있는 코드를 불러 수행한다.
스택과 큐 자료 구조
- 스택 영역을 알아보기 전에 Stack이라는 자료구조에 대해서 알아봐야 한다. 자료구조란 데이터를 어떤 식으로 보관하고 관리하는 구조에 대해서 말하는것이다. 그 중에서 Stack이라는 구조가 있다.
- 스택 자료구조는 위에만 뻥 뚤려있는 통의 구조로 되어있으며 마지막에 넣은 데이터가 제일 위에 있으며 다시 데이터를 꺼낼 때는 마지막 데이터부터 나오게 되는 후입 선출(LIFO, Last In First Out) 구조를 가지게 된다.
- 선입 선출 : 먼저 넣은게 먼저 나오는 자료구조로 큐 자료구조라고 한다. 스택과는 반대로 위아래 뚤려있으며 넣는것은 앞에서 넣고 빼는것은 뒤에서 빼는 형식이다. 가장 먼저 넣은 물건부터 빼는 구조이다.
- 이 두가지의 자료구조는 프로그램에서 많이 쓰이는 구조이다.
스택영역, 스택영역 과 힙 영역
- 자바는 스택영역을 통하여 메서드와 지역변수 혹은 매개변수를 관리한다.
- 매서드를 계혹 호출하게 되면 스택 프레임이 쌓이게 된다. 스택 프레임이 제거되면 지역변수도 말소된다.
스택영역과 힙 영역
- 지역변수는 스택영역
- 객체의 인스턴스는 힙영역
- 메서드 영역
static 변수1

- 객체를 생성하기 위해 클래스를 정의 하였다. 객체를 생성할때마다 몆번째로 생성되었는지 알기위해 생성자에 count라는 필드에 ++연산자를 사용하여 생성될때마다 count값이 증가하도록 하였다.

- 하지만 이것은 의도와 다른값이 나온다. 원래대로라면 C객체의 count값은 3이 나와야하지만 여기서 객체지향에 대해서 이해하고 있다면 이것은 당연하다는것을 알 수 있다.
- 왜냐하면 객체가 생성이 될 때마다 메모리에 객체를 위한 공간 하나가 할당이 되는데 이것은 ABC각기 다른 공간에 각자 할당이 되기 때문에 count변수 자체의 값이 공유가 될 수 없다. 그렇기 때문에 초기값 0으로 초기화 되는 count변수가 생성될 때 증감식을 사용하더라도 계속 1인 이유를 알 수 있다.
static 변수2
- 스태틱을 사용하면 여러 객체들이 공용으로 사용할 수 있는 변수를 만들 수 있다.
- 필드에 static키워드를 붙이면 static변수가 된다.
- 객체가 생성되면 생성자에서 static변수인 count를 증가시킨다.

- 스태틱 변수를 사용하기 위해 Data3.count라고 적어 count변수를 사용하였다. 그런데 객체명이 아닌 Data3이라는 클레스 이름을 직접적어 클래스를 참조하였다.
- static이 붙은 필드는 힙이 아닌 메서드 영역의 static영역에서 관리한다. 쉽게 이야기 하면 붕어빵 틀에서 특별하게 관리하는 변수이다.
- static변수를 생성자에서 사용할 때 클래스명.을 사용하여 static변수를 초기화 해야하지만 내것은 내가 관리하기 때문에 클래스 명을 붙여줄 필요가 없다.
- 메서드영역에서 관리하는것은 여러 객체들이 공용으로 사용한다는것이다.
- static변수는 붕어빵 틀에서 특별하게 관리하는 변수이다. 붕어빵 틀은 하나만 존재하며 static도 하나만 존재한다.
static 변수3
용어 정리
- 필드는 static이 붙은것과 안 붙은것으로 나뉘어서 분류할 수 있다.
인스턴스 변수 : static이 붙지 않은 변수
- static이 붙지 않는 변수는 객체를 생성해야만 사용할 수 있다.
- 인스턴스 변수는 인스턴스가 만들어질때마다 새로 만들어진다.
클래스 변수 : static이 붙은 변수
- 클래스에 소속된 변수이다.
- static이 붙은 변수는 인스턴스와 무관하며 클레스 자체에 소속이 되어있으며 자바 프로그램이 실행이 될 때 하나만 만들어진다.
- 인스턴스와 다르게 여러곳에서 공유하는 목적으로 사용되기 때문이다.

- 자바가 로딩이 될 때 클래스 로더가 클래스 정보를 읽을 때 static 영역에 할당하여 스태틱 변수를 생성하고 자바가 끝날때까지 만들 수 있다.
변수와 생명주기
- 지역 변수(매개변수 포함) : 지역변수는 스택변수에 있는 스택 프레임 안에 보관이 된다. 메서드가 제거 되면 스택 프레임이 제거가 되는데 이때 지역변수도 같이 소멸이 되며 변수중 생명주기가 제일 짧다.
- 인스턴스 변수: 객체의 변수를 인스턴스 변수라고 한다. 힙 영역에 생존하고 있으며 GC가 발생하기 전까지 생존해 있으며 지역변수보다 생존주기가 길다.
- 클래스 변수 : 메서드 영역에 스태틱 영역에 보관되는 변수로 JVM이 실행되어 클래스 정보를 읽을 때 생성이 되며 클래스로 생성되는 객체 전체가 공유하는 변수라 딱 하나만 생성이 된다. JVM이 종료될때까지 생존해있는다.
힙 영역에 있는 new하면서 생성이 되고 GC가 발동되면 사라지며 힙영역에 계속 생성 파괴가 되기 때문에 동적변수라고 한다. 하지만 static은 정적변수인데 한번 생성 되면 프로그램이 끝날 때까지 우직하게 생성되어 있기 때문에 정적변수라고 한다.
정적변수 접근법
- static변수는 클래스를 통해 접근할 수 있으며 인스턴스를 통해서도 접근이 가능하다.
- 인스턴스로 static변수에 접근을 하면 우슨 힙영역에 인스턴스 변수에 접근하였더니 접근하려고 했던 변수가 static변수였다면 다시 메소드 영역의 static영역으로 가서 접근한다.
- 인스턴스를 통한 static접근은 권장하지 않는다. 왜냐하면 명확하지 않기 때문이다. 인스턴스 변수에 접근하는것처럼 보이기 때문이다.
static 메서드 1
- static으로 하는 이유는 우선 객체에 필드도 없이 메소드가 달랑 있을 때 기능만 제공할 때 static으로 설정한다.
- 메서드에 static키워드를 붙이면 인스턴스 생성 없이 클래스 명으로 호출하여 바로 사용이 가능하다.
- static메서드를 클래스 메서드라고도 하는데 객체 생성 없이 클래스 그 자체로 호출하는것처럼 느껴지기 때문이다.
- 인스턴스 필요 없는 필드가 없이 로직만 있는 메서드라면 클래스 생성 없이 메서드만 불러와서 사용가능한 static메서드를 사용하는것도 좋다.
static 메서드2
- 스태틱 메서드를 언제나 사용할 수 있는것은 아니다.
- static메서드는 static만 사용할 수 있다고 한다. 클래스 내부 기능을 사용할 때 static이 붙은 정적 변수 정적 메서드만 사용가능
- static은 클래스 소속이며 클래스 소속인 static변수 static메서드가 있다.
- 클래스 내부 기능을 사용할 때 인스턴스 변수를 사용할 수 없다.

- 인스턴스변수 메소드는 스태틱 메소드에서 생성할 수 없다. 인스턴스 변수는 객체를 생성해야만 사용할 수 있는 변수인데 일단 static변수 메소드는 클래스 그 자체로 사용이 가능하며 객체를 생성하지 않는다 그렇기에 객체를 생성해야만 사용할 수 있는 인스턴스 변수를 static메소드에서 사용하거나 호출하면 컴파일 오류가 발생할 수 밖에 없다.
- 객체를 생성하지 않고 클래스명으로 사용하기 때문에 참조값을 알 수 없다. 하지만 참조값 객체를 념겨주면 스태틱 메서드에서도 인스턴스 변수 혹은 메서드를 사용할 수 있다.

- 반대로 instance변수 메소드는 사용할 수 있는데 앞에 클래스명이 생략되었으며 실제로는 클래스명이 있기에 사용가능
static 메서드3
main()메서드는 정적 메서드
- 인스턴스 생성 없이 대표적으로 실행되는 정적 메서드 이다.
- 정적 메서드는 정적 메서드만 호출할 수 있다.
- 메인 메서드가 같은 클래스의 메서드를 호출하기 위해서 정적으로 선언하고 메인 메서드 내부에서 메서드를 호출하였다.
- 정리해서 말하자면 스태틱인 메서드라면 스태틱 메서드만 호출할 수 있다. 왜냐하면 인스턴스 메서드를 호출하기 위해서는 객체생성을 해야하는데 객체생성을 하지 않은 이상 정적메서드에서는 인스턴스 메서드를 사용할 수 없다.