Technical Note/SERVER PERFORMANCE

JVM Memory 운용 모델

 

1. System Memory Model
java Test이 발생하고나서의 상황
---------------------------------------------
- 구획별 메모리는 64KB단위로 구분되어 있습니다.

┌────────────┐CS: Code Segment
│[코드 영역]                    │ 
│Test Class의 Source가    │ 
│등록되는 영역                 │ 
├────────────┤DS: Data Segment
│[Data 영역]                    │
│static변수,                     │
│static 메소드 저장           │
│main()                           │ 
│객체를 만들지 않아도       │
│이영역의 요소 사용가능    │
├────────────┤SS: Stack Segment
│[Stack 영역]                  │
│메소드가 사용하는 영역    │
│메소드 안에서 선언되는    │ 
│지역변수가 선언,             │
│메소드 처리가 끝나면       │ 
│메모리가 자동으로           │ 
│회수됨                           │ 
├────────────┤
│[Heap 영역]                   │
│객체가 생성되면              │
│존재하는 영역,                │
│RAM의 양에 따라 무한대  │
│GC의 대상이 되는 영역    │
└────────────┘

 

 

 

2. JVM Memory Model

Code Area ----- Data  ---- Stack --------------------- Index Table ----- Heap
                        Area                                                   Hash Table
----------------------------------------------------------------------------------------
Source              Static        메소드가 사용하는 영역          레퍼런스 값          주소
                        변수
                        메소드
----------------------------------------------------------------------------------------
메소드(공유)                      객체 변수1                            this, super       멤버변수  
int k=0;                              지역 변수                                                  인스턴스 변수
int m = 0;                           객체 변수2
int tot = 0;                          Test obj = new Test()  ---->  1000 0xFF00      0xFF00 int k...
int Total(){}                       Test obj2 = new Test()  --->  1001 0xFF08      0xFF08 int k...
                                       obj2 = obj;

                                

                                       Test obj3 = new Test()
                                       obj.tot = obj.Total(); 
                                       obj3.tot = obj3.Total();          

 


▩ static 변수(정적 변수, 클래스 변수), static method(클래스 메소드)
   - 자바 JVM으로 소스가 적재될시에 자동으로 Data Area에 메모리 할당을 받습니다.


   - new를 이용해 객체를 만들지 않고 사용 가능합니다.


   - 색상 정보등 단순한 값을 참조할 경우와 값을 편집하는 경우에 사용합니다.


   - static 변수는 객체 생성시에 오로지 하나만 생성됩니다.


   - static 변수는 객체 생성시에 오로지 하나만 생성됨으로 클래스 변수라고 합니다.


   - static변수는 DS(Data Segment) 데이터 영역을 사용합니다.

 

1. Hash Code의 출력
   - 객체의 Hash Code는 SUN에서 지정한 JVM의 해시알고리즘에 의해 해시코드가 산출됩니다.

   - String은 객체변수의 값이 같을 경우 즉 같은 문자열을 가지고 있으면 Hash code를 공유합니다.


     String str1 = "왕눈이";
     String str2 = "왕눈이";
     
     str1.hashCode() = str2.hashCode();


>>>>> HashCodeTestMain.java
class HashCodeTest {
    //멤버 변수, instance 변수, heap, 객체 사이트 8바이트
    int kuk=100;
    int eng=100;
}

public class HashCodeTestMain {
    //Data Area
    public static void main(String[] args) {
        //Stack: hct1       Heap
        //객체 변수: Hash Code값을 가지고 있습니다.
        HashCodeTest hct1 = new HashCodeTest();

        System.out.println("hct1.hashcode:" + hct1.hashCode());
    }
}

 


출력 결과
---------
hct1.hashcode:7699183

 


2. static 변수는 객체를 만들지 않아도 접근할 수 있습니다.

>>>>> Scjp.java
class ScjpPass{
    //멤버 변수, Heap
    int t1=0;
    int t2=0;
    int t3=0;
    int t4=0;
    
    //클래스 변수, Data area
    static int BONUS=100; 
    
    //생성자, Source area
    public ScjpPass(){
    }
    
    //생성자, this = sp객체가 가지고 있는 hash code
    //sp객체의 heap메모리를 공유하게됩니다.
    //int t1, int t2, int t3, int t4: Stack
    public ScjpPass(int t1, int t2, int t3, int t4){
        //Heap = Stack
        this.t1 = t1;
        this.t2 = t2;
        this.t3 = t3;
        this.t4 = t4;        
    }
    
}


public class Scjp {
    public static void main(String[] args) {
        System.out.println("ScjpPass.BONUS: " + ScjpPass.BONUS);  
        
        //t1은 static이 아님으로 클래스명으로 접근 할 수 없습니다.
        //System.out.println(ScjpPass.t1);
        //heap memory 할당
        ScjpPass sp = new ScjpPass(85, 90, 80, 70);
        System.out.println("sp.t1: " + sp.t1);
        //static변수는 클래스명으로 접근을 권장합니다.
        //System.out.println("sp.BONUS: " + sp.BONUS);
    }
}

 


3. static 메소드는 객체를 만들지 않고도 호출할 수 있습니다.
   - wrapper 클래스에서 많이 사용되며 단순 기능만을 사용할 경우 구현합니다.

 

>>>>> SCWCDmain.java
//하나의 java 파일안에 클래스가 2개이상 존재하는 경우
//main()메소드가 있는 오직 하나의 클래스만 public을 선업합니다.
//일반적으로 main()가 있으면 무조건 public을 선언하며
//파일명은 public 클래스명과 일치해야 합니다.

class SCWCD{
    int t1=0;
    int t2=0;
    int t3=0;
    int t4=0;
    static int BONUS=100; 
        
    public SCWCD(){
    }
    
    public SCWCD(int t1, int t2, int t3, int t4){
        this.t1 = t1;
        this.t2 = t2;
        this.t3 = t3;
        this.t4 = t4;        
    }
    
    public String pass(){
        String msg=null;
        if (t1 >= 65 && t2 >=65 && t3 >=65 && t4>=65){
            msg="축하합니다. 합격입니다.";
        }else{
            msg="축하합니다. 불합격입니다.";
        }
        return msg;
    }

    //클래스 메소드 
    public static void prLine(){
        System.out.println("****************");
        System.out.println("   ITWILL       ");
        System.out.println("         JAVA   ");
        System.out.println("****************");
    }
}

 

public class SCWCDmain {
    public static void main(String[] args) {
        //객체를 만들지 않고도 호출가능합니다.
        SCWCD sc = new SCWCD();
        //객체명.멤버변수, 멤버 메소드
        sc.t1 = 100;
        //sc.prLine();
        
        //클래스.static 메소드명
        SCWCD.prLine(); 
    }
}

 


4. 객체를 생성하면 멤버변수는 전부 기본값이나 생성자에서 지정한 값으로 초기화됩니다. 
   하지만 static변수는 프로그램을 실행시 최초 한번만 특정값으로 초기화되고

   (여기서는 0으로 초기화) 더 이상 초기화가 되지않습니다. 
   따라서 한번 만들어진 static변수는 계속적으로 값이 증가 및 감소됩니다.
   - static 변수는 객체를 여러번 생성해도 한번만 생성이 됩니다.
   - static 변수는 멤버 메소드에 선언할 수 없습니다.

 

>>>>> StaticDemo.java
class Box {
  //인스턴스 변수, 전역변수(객체를 생성시마다 초기화됩니다.)   
  int         cnt   = 0;
  
  //단 1회만 초기화 됩니다. 소스 로딩시에 메모리를 
  //한번만 할당 받습니다.
  static long boxID = 0;
  
  public Box() {
    long count=0;  
    boxID = boxID + 1; //static variable
    cnt = cnt + 1;    //member variable
    System.out.println("cnt: " + cnt);
    System.out.println("BoxID: "+ boxID );
    
  }
  
  //멤버 메소드에서는 static변수를 선언할수 없습니다.
  /*
  public void staticTest(){
      static long count=0;
      count=count+1;
      
  }
  */
  
  //static(class) 메소드에 static 변수를 선언할 수 없습니다.
  /*
  public static void staticTest2(){
      static long count=0;
      count=count+1;
      
  }
  */
  
}
  
public class StaticDemo {
    public static void main(String args[]) {
        //객체 생성  
        Box mybox1 = new Box();
        Box mybox2 = new Box();
        Box mybox3 = new Box();
    }
}

 

 


▩ 값을 변경할 수 없는 final 변수(상수 선언)
   - 값을 변경할 수가 없습니다.

   - 값을 고정할 필요가 있는 코드와 같은 형태의 데이터에 사용합니다.
      예)1년 12달, 요일, 주7일


>>>>> Finalmain.java
class Final{
    int money=10000;
    final int day=7;    //1주
    final int week = 4; //한달
    
    //상수 선언
    final static int month=12; //1년
    
    //생성자가 존재 하지만 아무런 처리를 하지 않습니다.
    public Final(){}     
}

public class Finalmain {

    public static void main(String[] args) {
        Final fi = new Final();
        fi.money = 15000;
        //final변수는 값을 변경(대입)할 수 없습니다. 
        //fi.day = 10;
        System.out.println("1주일 용돈:" + fi.money * fi.day);
        System.out.println("1년" + Final.month + "달");
        //Final.month = 20000;
    }
}