클래스 변수 생성 시기가 클래스가 메모리에 올라갈때??

 

1. 웹로직클래스경로를 잡아놓고 가동 시키고 해당 경로에 MyStringUtil이라는게
있고 이 클래스의 변수가 String static mString = "test"; 이렇게선언되어있으면
웹로직이 성공적으로 가동되면 이 클래스는 바로 메모리에 올라가서 
jsp에 <%!= MyStringUtil.mString %> 이렇개 사용가능 합니다.
모든 사용자가 같은 값을 갖습니다. 어차치 변수값이 다이나믹하게 선언이 않되니까요

2. 인스턴스변수는 MyBuisLogic logic = new MyBuisLogic() ;
이렇게 jsp안에서 한다음 logic.mString 이렇게 쓰는것을 의미합니다.
사이트에 3명의 사용자가 로그인(3번의 new 호출)하고 
그 사용자 3명의 세션이 모두 Active할때
서로 다른저장공간을 가지는 변수로 관리되서 다른유저의 
if(logic == logic) 하면 다르다고 나올겁니다.. 

3. 지역변수는 메소드 시작되면 메모리에 올라가고 메소드 종료되면 메모리에 해제
하지만 GC에 의해서 실제로 메모리에서 사라지는 시점은 application에 따라서 다름
MyBuisLogic logic = new MyBuisLogic();하고
logic.doIt() ; ==> 이때 doIt 내부에 선언한 변수 입니다.


아하 그렇군요. 
그럼 웹로직 클래스패스 경로에 있는 모든 클래스들을 다 체크해서 메모리에 올리는건가요 ?

그럼 메소드 같은 경우도 public static 으로 선언된것들도 다 체크하겠군요.

static 를 함부로 사용하면 안되겠네요;;;



1. static은 클래스 로딩시에 같이 초기화 됩니다. JVM은 특정 클래스를 사용하기 전까지는 static initializer 및 static 변수에 대한 초기화를 시작하지 않습니다.
2. 인스턴스 변수는 객체를 담는 변수입니다. 객체는 new 연산자 뿐 아니라 ObjectStream으로 부터의 복원, clone() 등의 방법을 통해서 생성될 수 있습니다.
3. 지역 변수는 메서드에서 호출될 때 이용되며 JVM이 코드를 읽어 들일 때 미리 해당 메서드 프레임에 인덱스를 생성해 둡니다. 책에서는 잘못 설명한 듯 하네요. 메서드 호출 시에는 변수가 생성되는 것이 아니라 인스턴스가 생성되어 할당됩니다.

정리하면 모든 변수에 대한 Symbol은 컴파일 시점에 생성됩니다



메모리 영역은 method 영역 , stack , heap 영역이 있는데요... 
method 영역은 static 영역이라고 하고 stack영역은 non-static 영역이라고 합니다. 객체가 생성되면 heap영역에서 생성이 되고 인스턴스 변수라 할 수 있는 메모리 주소는stack에 쌓이게 됩니다. 메인 메소드와 객체 메소드 static 변수는 메소드 영역에서 존재하게 되구요.


 static 변수는 컴파일 시점에 생성이 되지만 참조변수는 new 시점에 올라가게 됩니다....

static영역서서는 non-static을 바라 볼 수 없지만 non-static 영역에서는static 영역을 볼 수 있습니다.

객체는 heap영역에 존재하고 참조변수는 stack 영역에 쌓이게 됩니다.

^^ 메모리에 관한 부분을 확실히 해두세요.... 

또한 member variable 과 local variable 들은 클래스 내에서 어떤 위치에 선언이 되어 있는가에 따라 붙혀지는 이름입니다.


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
31
 
public class Start5 {
 
    static int share;
 
    public static void main(String[] args) {
 
        //int share = 55;
        share =55;
//        int k = fun(a,b);
        int k = fun(57);
 
        System.out.println(share); //12
        System.out.println(k); //-2
        //12,-2출력이 정상
        //처음에 55,-2나온 이유는 main 함수 안에 int share = 55를 넣어서 지역변수로 인식해서 다시 초기화 됨
        //static int share해놓고 main안에 share =55; 해놓으면 전역변수로 정의됨.
    }
 
 
    private static int fun(int m,int n){
//    public int fun(int m,int n){
 
            share = m+n; //12가 된다. fun함수호출로 인해55였던것이 12로 바뀐다.
 
            return m-n; //-2가 된다.
 
        }
    }
 
 
cs


static 변수는 알고 계신다는 가정 하에 간단하게 설명 하겠습니다.
static 변수란 한번 생성되면 선언문을 또 만나더라도 새로 생성되지 않게하는 키워드 입니다.
즉, 한번 메모리에 할당되면 더 이상 새로 할당되지 않게 한다는 의미입니다.

public class VariableScopeExam{
    static int value = 10;
    public static void main(String []args){
        System.out.println(value);
    }
}
public class VariableScopeExam{
    int value = 10;
    public static void main(String []args){
        VariableScopeExam ex = new VariableScopeExam();
        System.out.println(ex.value);
    }
}

일반적으로 자바에서 인스턴스 변수가 메모리에 할당되는 시기는 객체가 생성되었을 때 입니다.
두 번째 코드(static 사용 X)를 보시면
VariableScopeExam ex = new VariableScopeExam();
위 코드로 ex라는 객체가 만들어지는 순간 변수 value가 메모리에 할당 됩니다.

그러나, 첫번째 코드 클래스변수(static 사용)의 경우는 완전 다른 동작방식으로 진행됩니다.
클래스가 메모리에 할당 되는 순간, static으로 선언한 value도 메모리에 같이 할당되는 것 입니다.

메모리 할당 시기를 알고 보시면 더 이해하기 쉬울 것 입니다.
질문으로 돌아와서

public class VariableScopeExam{
    int value = 10;
    public static void main(String []args){
        System.out.println(value);
    }
}

이 경우는 value가 아직 메모리에 할당되지 않은 상태에서 사용하려 해서 오류가 발생한 것 입니다.

public class Car{
    int wheelCount;
}
public class StaticExam{
    public static void main(String []args){
        Car taxi = new Car(); // 메모리 할당
        Car suv = new Car(); // 메모리 할당

        ...
    }
}

이는 static을 붙이지 않았지만, 객체 선언 문장을 만나 메모리를 할당 받았기 때문에 오류가 발생하지 않는 것 입니다.

한번 이해하면 그리 어렵지 않은 개념입니다. 잘 이해안되는 부분은 댓글로 남겨주세요 :)

1 개의 답변

정찬형


또한 static을 명령어로 지정하는 이유는,
static의 특징이 프로그램이 시작하면서 따로 인스턴스 하지 않아도
프로그램의 시작과 동시에 static으로 선언된 것들은 메모리에 호출이 되어 지는데,
이렇게 호출된 것들은 다른 녀석들과는 다르게 프로그램이 종료되는 시점까지 계속 유지가 된다는 점이다.
다른 클래스, 메소드, 변수 등의 경우 Java Virtual Machine의 Garbage Collector에 의해
인스턴스화 되어 사용이 되어진다 하더라도, 일정 용도를 끝 마친 후에는 다시 메모리에서 삭제가 되거나,
다른 부분에서 참조가 되지 않는 부분 등이 있는데,
static으로 선언된 것은 끝까지 살아남아 계속 참조를 할 수 있는 특징이 있으므로,
프로그램에서 시작과 끝을 함께하는 main 메소드가 일정 시간만 살아있고 폐기되어서는 곤란하므로
계속 살아남아 역할을 하기위해서는 static 명령어가 꼭 필요하다고 할 수 있다.


JAVA 는 어플리케이션이 실행되면 제일먼저 메인(main)메소드를 실행한다 입니다.


그렇다면 public static void 는 무엇이며 괄호() 안에 들어간 String[] args 는 무엇인가 궁금하겠죠..


지금 처음하시는 분들이라면 잘이해가 안되실테니 자세한 내용은 나중에 올리고 지금은 간단하게만 설명하겠습니다.


public 은 접근제어자입니다.

접근제어자는 외부에서 접근할수 있는 일종의 제약입니다. 종류는 제약이 강한순서대로 private -> protected -> public 이 있으며 defualt 는 클래스 내부와 동일 패키지에서 접근할 수 있습니다. 

public 은 어느곳에서든 해당 객체를 참조할수있다는 의미입니다.


그렇다면 아무곳에서나 메인메소드를 호출하면 되는건가요?

라는 생각을 해볼수있는데. 위를 보면 자바 어플리케이션이 실행되면

제일먼저 메인메소드를 실행한다고 알려드렸습니다


따라서 프로그램의 시작은 메인이기때문에 난 메인메소드에서는 정의만 하고 다른곳에서 이것을 호출할거야 라는 의미는 사용할수 없습니다.


만약 main 메소드에서는 hello world 만 출력하고 다른 클래스 호출하여 메인메소드를 사용했을경우 무한히 hello world 출력이 반복되는 장면을 볼수있습니다.



static 은 이 함수가 정적 함수임을 의미합니다. 즉 가만히 있어도 되는? 라는 의미로 해석이 되는데요.. 

static 으로 함수 또는 클래스를 선언했을 경우에 해당 객체는 자바가 컴파일 되는 순간 정의가 됩니다.  그리고 이후 static 이 아닌 객체가 정의가 되죠


따라서 일단 static 객체에서 static 이 아닌 객체를 호출하는것은 불가능합니다.

static 이 먼저 정의가 되기때문에 아직 정의되지 않은 객체는 호출할수 없기때문입니다. 순서를 생각해보면 금방 이해될 내용입니다.


자세한 내용은 나중에 다시한번 설명드리겠습니다.


void 는 나는 그냥 실행만 할뿐.. 나에게 다른걸 바라지마.. 너에게 아무것도 돌려주지않아.. 라고 장난 치듯 얘기할수있겠네요..


말그래도 void 는 리턴되는 값이 없습니다. 단지 해당 함수가 종료된후 호출한 부분으로 이동할뿐입니다.


더쉽게 이해하자면 void 자리에 int 를 넣을경우 어떠한 처리를 실핸한후 정수형 데이터를 돌려보내겠다는 뜻이며 String 이 들어갈경우 문자형 데이터를 돌려보내겠다는 의미입니다..  이해되셨나요?



자! 지금까지 거의다 도착했습니다. 지금까지 이야기 한것을 종합해보면


이 메인메소드는 자바 어플리케이션 실행시 제일먼저 동작하며 어느 객체에서든 접근할수 있으며 자바가 컴파일 되는 순간 정의되는 돌려주는 값이없는 함수구나~~~~


정도로 의미했으면 전부는 아니더라도 어느정도 다 온것같습니다.. 

쉽게쉽게 생각하자고요 우리가 만든 프로그램이 아니잖아요 ^^


마지막으로 괄호() 안에 들어가는 String[] args 는 무엇일까요

이건 매개변수의 의미와 배열과 String 클래스를 배워야 아는부분이라서 

지금상태에서 전부다 이해할순없어도 간단하게 설명해보겠습니다.


String 은 문자열을 의미합니다. " " 쌍다음표 안에들어가는 문자들의 집합 즉

"Hello World" 와 같은 데이터의 형태를 String 이라는 클래스변수로 정의하겠다는 의미이며 


[] 는 배열을 의미합니다.

연속적인 데이터를 하나의 변수에 넣고싶을때 즉 배열에는 인덱스가 있고

[0] , [1], [2] 와같이 인덱스로 구분되는 공간에 데이터를 넣겠다는 의미이며


args 는 단순한 변수명입니다. 아무변수명이나 넣어도 상관없죠~ 


이걸 조합하면 


연속적인 문자열 데이터가 들어가는 저장공간 이라고 생각하며 됩니다.



출처: https://javacpro.tistory.com/11 [버물리의 IT공부]


main함수는 프로그램의 시작부터 끝까지 있는 함수이다.

*public을 사용하는 이유?

보통 다른 클래스들의 메소드들을 호출해서 사용하는데, main자체가 다른곳에서 접근을 허용하지 않으면 문제가 발생하기 떄문에

public을 사용

*static을 사용하는 이유?

static의 특징으로는 따로 인스턴스화 하지 않아도 되고, 시작과 동시에 메모리에 호출되어진다는 점이다.

즉, 프로그램이 종료될 때까지 계속 유지가 되는데, static이 있기 때문에 계속 참조할 수 있고,GC(?)에 의해서 사라질 염려가

없기 때문에 static사용한다.

*void을 사용하는 이유?

main함수 자체가 시작과 끝을 의미하는 것인데, 종료되는 시점에서 무슨 값을 반환한다 해서 의미가 있다고 생각하지 않는다. 그래서

void로 설정해야 한다.

*args[] 를 사용하는 이유?

처음 프로그램을 실행하는 순간 외부 값을 가져와서 프로그램 안에서 사용하고자 할때, 메모리에 저장할 공간을 미리 선언해 두기 위해서 사용한다.



⌘ : command

⌃ : control

⇧ : shift

⌥ : option(alt)

⎋ : esc

⏎ : return(enter)

⇥ : tab

### 파일

- ⌘O : 클래스 찾기 - 단어사이 대문자로 조회하면 더 이득

- ⌘⇧O : 파일 찾기 - 유사 단축키로 ⇧⇧ 도 많이 사용함

- ⌘E : 최근 사용 파일 찾기

- ⌃⇥ : 최근 파일로 이동 - 위 ⌘E 와 유사하나 UX가 약간 다름

### Layout

- ⌘1 : Project view

- ⌘3 : Find view

- ⌘4 : Run view

- ⌘8 : Hierarchy - ⌃⌥H 로 메소드 호출을 찾으면 노출됨

- ⌘9 : Version Control - git, task 관리

- ⇧⎋ : 활성화된(현재 선택된) Layout 닫기

### Refector

- ⌘⌥M : 메서드 분리

- ⌘⌥C : 상수 분리 생성 (public static final ...)

- ⌘⌥F : 필드(객체변수) 분리

- ⌘⌥V : 지역변수 분리

- ⇧ F6 : rename

- ⌘ F6 : 메서드 시그니쳐(명칭, 반환타입, 파라메터타입과 명칭, 접근자 등) 변경

### 에디터

- ⌥⏎ : Quick fix - 오류 해결 솔루션 제시

- ⌘⇧↑, ⌘⇧↓ : 선택된 코드 영역 위, 아래로 이동

- ⌘ Del : 한 줄 삭제

- ⌘⇧] : 에디터 탭 기준 오른쪽으로 이동

- ⌘⇧[ : 에디터 탭 기준 왼쪽으로 이동

- ⌥↑ : 커서 기준으로 단위 영역(단어, 영역, 문장, 메서드 등) 선택

- ⌘ F12 : 현재 클래스 필드, 메서드 등 목록 노출 - lombok 사용할 시 편함

- ⌘N : 각종 코드 생성 (getter, setter, override, DI 등)

- ⌃O : 상위클래스 override

- ⌃⌥O : Auto import

- ⌥⇥ : 스플릿(화면분할) 상태에서 화면 간 이동

- ⌥ F1 then 1 or ⏎ : 현재파일 Project View 에서

활성화

code completion : shift + command + space

### 실행

- ⌘ F9 : 컴파일

- ⌘R : Run View에서 현재 포커싱 실행 (실행 중이면 재실행)

- ⌘ F2 : Run View에서 현재 활성화된 실행을 Kill

- ⌃R : 최근 실행한 것을 다시 실행

- ⌃⌥R : 현재 커서나 포커싱 된 파일에 실행가능한 것을 노출 후 선택 실행 가능

보통 단위테스트 시 해당 커서가 메서드안에 있는 상태에서 위 단축키를 누르고 2를 누르면 바로 메소드 테스트 실행

- ⌃D : 최근 실행한 것을 다시 실행 - 디버깅 모드

- ⌃⌥D : 현재 커서나 포커싱 된 파일에 실행가능한 것을 노출 후 선택 실행 가능 - 디버깅 모드

### 생성

- ⌘⇧T : 테스트케이스생성

이후 ⌘N 을 이용하면 테스트메서드 생성이 편리함

### 이동

- ⌘B : 클라이언트 코드에서 해당 메소드 선언으로 이동

- ⌘⌥B : 클라이언트 코드에서 해당 메소드 구현으로 이동 - 강추

- ⌘U : 구상클래스에서 해당 메소드 선언으로 이동

- ⌘⌥←, ⌘⌥→ : 이전, 다음 작업영역으로 이동

### 작업(형상)관리

- ⌘K : 커밋

커밋 확인 후 ⌃⏎를 치면 됨

만약 review 여부를 물으면 Commit 버튼을 ⇥으로 포커싱 후 Space를 입력

- ⌥⇧N : Task 추가 - ⌘9 와 연계하면 작업관리 시 편함

- ⌥⇧C : Recent Changes

### Multiline

- ⌘⌃G : 커서가 위치한 단어 기준 multiline 제어

- ⌘⇧8 + ⇧↑, ⇧↓ : multiline 모드 활성화 후 라인 선택

- ⌥⇧ MouseLeftClick : 마우스로 클릭한 위치 기준으로 multiline 제어

### 검색

- ⌘⇧F : 문자열 전체 검색

### 바로가기

- ⌘, : 환경설정

- ⌘; : 프로젝트 환경설정

### Syntax

- iter : for-each 구문 생성

- fori : for 구문 생성

- psfs : public static final String

- psfi : public static final int

- psvm : public static void main(String[] args)

- thr : throw new

- sout : Systoem.out.println()

*참고

http://redutan.github.io/2016/03/23/intellij-favorite-keymap-osx


+ Recent posts