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;
}
}