[Java] JVM의 메모리 구조

JVM의 메모리 구조




응용프로그램이 실행되면,

JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고

JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.

 

1. 메서드 영역 (Method Area)  - 클래스

 프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스의 클래스파일(*.class)을 읽어서 분석하여 클래스에 대한 정보 (클래스 데이터)를 이곳에 저장한다. 이때, 그 클래스의 클래스 변수(class variable)도 이 영역에 함께 생성된다.

 

2. 힙 (Heap) -  인스턴스

 인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성된다. 즉, 인스턴스 변수(Instance Variable)들이 생성되는 공간.

 

3호출스택(call stack 또는 execution stack)  - 메서드

 호출스택은 메서드의 작업에 필요한 메모리 공간을 제공한다.

 메서드가 호출되면, 호출스택에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수(매개변수 포함)들과 연산의 중간결과 등을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리 공간은 반환되어 비워진다.

 

 호출 스택의 제일 상위에 위치하는 메서드가 현재 실행 중인 메서드이며, 나머지는 대기상태에 있게 된다.

아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드 이다.


main()
{
    // 멤버변수 x 가 있음.
    Data d = new Data();  
    change(d.x);
}

change(int x){}


 

이러면 기본형 매개변수로 변수의 값이 변하지는 않음.

대신


main()
{
    Data d = new Data();
    change(d);
}
change(Data d){}


이러면 참조형 매개 변수로 값이 변해요.

 

 

 

 

 

 

 

[Java] 반환값 return의 TIP

 반환값 return의 TIP




return문을 여러번 쓰는 것보다 가능하면 아래의 오른쪽 코드와 같이 변수를 사용해서 

리턴값을 저장했다가 마지막에 한번만 사용하는 것이 좋다.

 

int max(int a, int b)
{
    if( a > b)
        return a;
    else
        return b;
}
 
int max(int a, int b)
{
    int result = 0;
    if( a > b)
        result = a;
    else
        result =  b;
 
    return resultt;
}



리턴 값이 있는 메서드를 리턴값이 없는 메서드로 바꾸는 방법!


참조형 매개변수를 활용하면 리턴값이 없어도 메서드의 실행결과를 얻어 올 수 있다.!

이방법을 응용하면 여러 개의 값을 리턴 받는것과 같은 효과를 얻을 수 있다.


int add(int a, int b)
{
    return a+b;
}
 
void add(int a, int b, int[] result)
{
    result[0] = a + b;
}


 

 

 

[Java] 배열에 대한 이야기

배열에 대한 이야기





배열을 선언하는 방법


 

타입[] 변수이름 ;

타입 변수이름[] ;


이 두가지 모두 가능하지만! 타입[] 변수이름을 사용하자.

 


 배열 선언

 참조 변수를 위한 공간을 만듦

 배열 생성

 저장할 수 있는 공간을 만듦

 

사실 배열도 객체라서 멤버변수와 메서드를 가지고 있다. 멤버변수 length는 배열의 크기에 대한 정보를 가지고 있다. 배열을 for문을 돌릴 때 length를 이용하여 돌리는 것이 좋다.  

 

 




배열 초기화의 두가지 방법

 


int[] num = { 1, 2, 3, 4, 5};

int[] num = new int[][ 1,2,3,4,5};  


이 두가지 모두 가능하지만! 

두번째 방법은 선언과 초기화를 따로 한다면 자칫 에러가 발생한다.

int[] num = { 1, 2, 3, 4, 5};이 방법을 사용하자.

 

 

 



String 클래스의 charAt(int index)는 문자열 중에서 index번째 위치에 있는 문자를 반환한다. 배열처럼 0부터 시작함.

 


public static void main(String[] args) 
{ 
  String src = "LGH";
  for(int i=0; i< src.length() ; i++)
  {
    System.out.println("src.cahrAt("+i+") : " + src.charAt(i));
  }
 }


 



다차원 배열

 


타입[][] 변수 이름 ;

 

int[2][3] num;로 선언했을 때

 

num.length는 몇? 2

num[0].length는 몇? 3

 

num[0].length는 배열 참조변수 num[0]이 참조하고 있는 배열의 크기므로 3이다.

 

2차원 배열 for문은 코드는 아래와 같다.



for(int i =0; i< num.length ; i++)
{
    for(int j=0; j< num[i].length ; j++)
    {
        num[i][j] = 10;
    }
}


 



가변 배열

 

int[][] num = new in[5][];

num[0] = new int[1];

num[1] = new int[4];

num[2] = new int[5];

num[3] = new int[2];

num[4] = new int[3];

 

마지막 차수의 크기를 지정하지 않고 각기 다른 크기로 배열을 생성하면 된다.


 



배열의 복사

 

배열 간의 내용을 복사하려면 for문을 사용하거나 System클래스의 arraycopy()를 사용하면 된다.

 

arraycopy()는 배열에 저장되어 있는 값만 복사하기 때문에 참조변수 배열인 경우에는 단지 주소값만을 복사할 뿐 참조변수가 가리키고 있는 객체를 복사하지는 않는다.

 

System.arraycopy( arr1, 0, arr2, 0, arr1.length); 

arr1[0]에서 arr2[0]으로 arr1.length개의 데이터를 복사 한다.


arr1의 0 번째를 arr2 0번째 부터 arr1.length개 복사해서 넣기


 

 

 

 

 

 

 

 

 

[Java] 조건문과 반복문에 대한 이야기


조건문과 반복문에 대한 이야기




if문


간단한 if문은 삼항 연산자 ( ? : )로 바꿀 수 있으면 바꾸는걸로!


public static  void main(String[] args)
{
    long startTime = System.currentTimeMillis();
    for(int i=0; i< 10000000000; i++){}
 
    long endTime = System.currentTimeMillis();
 
    System.out.println("시작 시간  : " + startTime);
    System.out.println("종료 시간  : " + endTime);
    System.out.println("소요 시간  : " + (endTime - startTime));
}


System.in.read()를 이용해서 화면을 통해 사용자로부터 입력을 받음. 

음? 화면에서 한번에 여러 글자를 입력할 수 있지만 사실 System.in.read()는 한 번에 한 문자 밖에 못읽는다.!?....

 

System.in.read()는 사용자가 입력한 문자가 'Ctrl + z'이면 -1을 반환한다.

 

 



Continue 문


반복문 내에서만 사용될 수 있으며, 반복문의 끝시점으로 이동하여 계속 반복문을 수행.


 

이름 붙은 반복문

 

여러 반복문이 중첩되어 있을 때 반복문 앞에 이름을 붙이고  break문과 continue문에 이름을 지정해 줌으로써 하나 이상의 반복문을 벗어나거나 반복을 건너뛸 수 있다.

 


public static void main(String[] args)
{
    //for문에 Loop1이라는 이름을 붙였다.
    Loop1 : for(int i=2; i <=9; i++)
    {
       for(int j=1; j<=9; j++)
       {
            if( j==5)
                  break Loop1;
                  break;
                  continue Loop1;
                  continue; 
                  ....
}



 

반복문에 이름을 붙여주고 break문에 반복문을 지정해주면 하나 이상의 반복문도 벗어날 수 있다.

 

[Java] 나머지 연산자 ' % ' 와 시프트 연산자 ' <<, >>, >>> ' 이야기

나머지 연산자 ' % ' 와 시프트 연산자 ' <<, >>, >>> ' 이야기




나머지 연산자 ' % '

 

boolean형을 제외하고 모든 기본형 변수에 사용할 수 있다.


짝수, 홀수 또는 배수 검사 등에 사용된다.

 

' a % b = c ' 라고 한다면 여기서 c는 a의 부호를 따라간다.

 

- 5  %  2 = -1

   %  2 =  1

- 5 %  -2 = -1 

 





쉬프트 연산자  ' <<  >> , >>> '

 

쉬프트 연산자는 정수형 변수에만 사용할 수 있는데, 피연산자의 각 자리 (2진수로 표현했을 때)를

오른쪽 또는 왼쪽으로 이동( Shift )한다.

 

오른쪽으로 n자리 이동하면, 피연산자를 2^n로 나눈 것과 같은 결과를 얻을 수 있고,

왼쪽으로 n자리 이동하면 2^n으로 곱한 것과 같은 결과를 얻을 수 있다.

 

 

 

 

 

[Java] 연산자 ( & , | , ~ , ! )에 대한 이야기

연산자 ( & , | , ~ , ! )에 대한 이야기





논리 연산자중에 AND 를 의미하는 '& ' 와 '&&'가 OR를 의미하는 ' | ' 와 ' || '보다 우선순위가 높다.

 

우선순위 : &  > ||


 AND와 OR가 함께 사용되는 경우에는 괄호를 사용해서 운선순위를 명확히 하는것이 좋다.

 

 




비트전환 연산자   ' ~ ' 는 정수형과 char형에만 사용될 수 있다.

피연산자를 2진수로 표현했을 때, 0은 1로 1은 0으로 바꾼다.

 

                                                    

   2진수

      10진수    

 0

0

0

 10

 1

1

0

0

1

 -11

 

그래서 연산자 ' ~ ' 에 의해 비트전환 되고 나면, 피연산자의 부호가 반대로 변경된다.

 

public static void main(String[] args) { byte b = 10; System.out.println ("a = " + a); System.out.println ("~a = " + ~a); System.out.println ("~a+1 = " + (~a+1); }

출력 결과


a = 10;

~a= -11;

~a+1 = -10;



따라서, 양수를 음수로 바꾸고 싶을땐?


~변수+1 '

 

연산자 '~ '는 피연산자의 타입이 int형 보다 작으면, int형으로 변환한 다음에 연산을 하기 때문에

연산결과를 저장하고 싶다면

int형 변수에 담거나, 캐스트 연산자를 사용해야한다.

 

public static void main(String[] args)
{
    byte a= 1;
    
    //'~'연산의 결과가 int형이라서 byte형 변수에 저장할 수 없다.
    //byte result = ~a;
 
    // 이렇게 캐스트 연산자를 사용하던지 해야함.
    byte result = (byte) ~a;              
}




논리부정 연산자 ' ! '

 

boolean형에만 사용할 수 있으며, 토글버튼(toggle button)을 논리적으로 구현할 수 있다.

 

ex>

boolean power = false;

power = !power;

[Java]Byte나 Short보다 int형을 쓰는 이유

Byte나 Short보다 int형을 쓰는 이유




JVM의 피연산자 스택(operand stack)

피연산자를 4 Byte단위로 저장하기 때문에

 

 

크기가 4 byte보다 작은 자료형( byte, short)의 값을 계산할 때4 byte로 변환하여 연산이 수행된다.

 

따라서 오히려 int형을 사용하는 것이 더 효율적이다.



[Java] 문자형 char 에 대한 이야기

char는 문자를 내부적으로 정수값 코드로 저장하기 때문에 정수형 ( byte, short , int ,long )과 밀접한 관계가 있다.


char는 자바에서 유니코드( 2 byte 문자 체계)를 사용하므로 2 byte.

 

C언어와 같은 프로그래밍 언어는 문자형의 경우 1 byte( ASCII코드 ) 의 크기를 갖지만,

java에서는 유니코드 (Unicode)문자 체계를 사용하기 때문에 크기가 2 byte이다.

 

 

여기서 잠깐!

 

유니코드란?


세계 각 국의 언어를 통일된 방법으로 표현할 수 있게 제안된 국제적인 코드 규약이다.

컴퓨터가 미국에서 개발되어져 영어를 바탕으로 정의되어 있다.

 

영어는 26자의 알파벳과 몇 가지 특수 문자를 표현하기에 1 byte로 충분했기 때문에

문자가 1 byte로 표현되고 있지만,

 

동양 3국의 한글, 한자 또는 일어 등과 같은 문자는 1 byte로는 표현이 불가능하기에

2 byte로 문자를 표현하는 유니코드가 만들어 졌다.

 

 



char형 변수에 문자를 저장할 때는 홀따옴표 ( ' ' )로 문자를 둘러싼다.

ex > char firstletter = ' A ' ;

 



char형 VS short형

 

크기가 모두 2 byte( 16 bit )로 표현할 수 있는 값의 개수는 65536개로 같다.

 

하지만!


 char 형

문자의 코드를 저장하므로 음수를 필요로 하지 않기 때문에 2진수로 표현했을 때 첫 번째 자리를 부호에 사용하지 않는다.

 short 형

 첫 번째 자리를 부호를 표현하는데 사용하기 때문에 서로 다른 범위를 갖는다.


만약에 어떤 문자의 유니코드를 알고 싶으면,

char형 변수를 정수형(int)으로 변환하면 된다.

 

char ch = 'A';

int code = (int ) ch;

 

변수에 문자를 저장하는 것 같지만 실제로는 정수값(유니코드)이 저장되는 것이다.

잊지말자 ! 모든 데이터는 숫자로 저장된다. !

 

 

[Java] Java 언어의 특징

자바 언어의 특징

 

 



1.  운영체제(Operating System, 플랫폼)에 독립적

 

운영체제의 종류에 관계없이 실행 가능하다.

 

일종의 에뮬레이터인

자바 가상 머신(JVM)을 통해서 가능한 일이다.

 

운영체제, 하드웨어 (X)

JVM하고만 통신하고 JVM이 자바 응용프로그램으로부터 전달받은 명령을 해당 운영체제가 이해 할 수 있도록 변환하여 전달한다.

 

자바 <독립> 운영체제

 

그러나,

JVM은 운영체제에 종속적이다.썬에서는 여러 운영체제에 설치할 수 있는 서로 다른 버전의 JVM을 제공하고 있다.

 

'한번 작성하면, 어디서나 실행된다. ( Write once, run anywhere)'라고 표현하기도 한다.

 



 

2. 객체 지향 언어이다.

상속, 캡슐화, 다형성이 잘 적용된 순수한 객체 지향 언어다.

 

3. 배우기가 쉽다.

간결하면서도 명료한 객체지향적 설계~

 



4. 자동 메모리 관리( Garbage Collection)

 

가비지컬렉터( Garbage Collector)가 자동적으로 메모리를 관리 해주기 때문에

 

프로그래머는 메모리를 따로 관리 하지 않아도 된다.

 

자동으로 메모리를 관리한다는 것이 다소 비효율적인 면도 있지만말이다... ㅋㅋ 괜춘함.

 

5. 네트워크와 분산 처리를 지원한다.

다양한 네트워크 프로그래밍 라이브러리(Java API)를 통해 비교적 짧은 시간에 네트워크 관련 프로그램을 쉽게 개발할 수 있도록 지원한다.

 

6. 멀티쓰레드를 지원한다.

자바에서 개발되는 멀티쓰레드( muti -thread) 프로그램은

시스템과 관계없이 구현가능하며, 관련된 라이브러리(JAVA API)가 제공되므로 구현이 쉽다.

여러 쓰레드에 대한 스케줄링을 자바 인터프리터 ???? 가 담당하게 된다.

 

7. 동적로딩(Dynamic Loading)을 지원한다.

 

실행 시에 모든 클래스가 로딩되지 않고,

필요한 시점에 클래스를 로딩하여 사용할 수 있다는 장점이 있다.

 

[Java] 변수에 대한 이야기

변수에 대한 이야기




변수의 타입에는 크게 기본형, 참조형으로 2가지로 나눌 수 있다.


참조형 객체의 주소를 저장한다.


Date today =null;

또는

Date today = new Date();

 

연산자 new의 연산결과생성된 객체의 주소이다.

대입연산자 '='에 의해서 참조변수 today에 저장되는 것이다.

 

 


 boolean  

 1 byte

 char       

 2 byte



char는 문자를 내부적으로 정수값 코드로 저장하기 때문에 정수형 ( byte, short , int ,long )과 밀접한 관계가 있다.


char형은 Java에서 유니코드(2 byte 문자 체계)를 사용하므로 2 byte입니다.



큰값을 다루어야 하는 경우가 아니라면 int 와 float를 사용하자.

 

int 형은 대략 9자리 수 ( 약 20억)의 값을 저장할 수 있다.

9자릿수에 가까운 자리 수 (6~8자리)의 수를 계산 할 때는 넉넉하게 long형(약 19자리)를 사용하는 것이 좋다.

 

 

정수형 변수는 자신이 저장할 수 있는 범위를 넘어서면최소값부터 다시 반복된다.

 

만일 000~ 999까지 표현 할 수 있는데

999를 넘어서면 ( 오버 플로우 발생 )

 

000부터 다시 반복한다.

 

따라서, byte의 경우 -128(최소값)부터 시작해서 127( 최대값)을 넘으면

다시 -128부터 시작하게 된다.