Java 학습공간

최신업데이트 일자 : 2015. 08. 28
추가할 내용 : 국내 자바도서 3권, Effective Java, 여러 Article, Java 7-8 업데이트 내용

자만은 금물
부족함은 모자름이 없다.
익숙해진 느낌이 든다면 부족해졌다 생각하자.


자바

완벽한 객체지향언어로서 코드의 화려함보다는 소프트웨어의 구조를 중요시한다


자바 바이트코드(Java bytecode)

자바 컴파일러에 의해서 생성되는 코드를 가리켜 “자바 바이트코드”라 하는데,
이는 자바 컴파일러에 의해서 생성되는 코드의 명령어 크기가 1바이트이기 때문에 붙여진 이름이다


자바가 지니는 속도의 핸디캡

  • 대부분의 소프트웨어는 속도보다 안전성이 우선시 된다
  • 물론 속도는 중요하다. 하지만 여기서 말하는 속도는 소프트웨어의 개발 속도이다
  • 개발중인 소프트웨어의 90% 이상은 인터넷, 네트워크 기반 소프트웨어이다
  • 인터넷, 네트워크상에서는 소프트웨어의 속도보다 데이터의 전송속도가 더 중요하다
  • 속도가 문제가 되면 대부분의 개발자들은 데이터베이스를 먼저 의심한다. 그리고 그곳에서 대부분 문제를 발견하고 해결한다


자바의 자료형

boolean 참과 거짓 1바이트 true, false
char 문자 2바이트 모든 유니코드 문자 (유니코드라 2바이트)
byte 정수 1바이트 -128 ~ 127
short 정수 2바이트 -32768 ~ 32767
int 정수 4바이트 -214783648 ~ 2147483647
long 정수 8바이트 -9223372036854775808
~ 9223372036854775807
float 실수 4바이트 -1.40 x 10^-45 ~ -3.40 x 10^38
+1.40 x 10^-45 ~ +3.40 x 10^38
double 실수 8바이트 -4.94 x 10^-324 ~ -1.79 x 10^308
+4.94 x 10^-324 ~ +1.79 x 10^308


자바의 정수형 연산

단순히 메모리 공간만 가지고 보면 적은 메모리를 사용하는 변수를 Short와 같은 자료형을 사용하는게 좋을것 같지만
중요한 사실은 정수연산의 관점에서는 다르다는 것이다.
일반적으로 우리가 사용하는 CPU는 int형 정수연산을 가장 고속으로 처리하게끔 설계되어 있다
따라서 자바는 정수형 연산을 진행할 때(덧셈이건 뺄셈이건), 모든 피연산자를 int형으로 변환하는 과정을 거친다.
때문에 정수형 연산을 위해서 short 자료형보다는 int형의 실행속도가 더 빠르다
단, long형에서의 int형으로의 변환은 일어나지 않는다


자바에서의 실수 자료형 선택기준

4바이트로 표현되는 float는 6자리의 정밀도 (소수점 이하 6자리 정밀도)를 가지고
double은 15자리의 정밀도(소수점 이하 15자리의 정밀도)를 갖기 때문에,
표현하고자 하는 값에서 요구하는 정밀도를 기준으로 자료형을 선택하게 된다
소수점 이하 15자리까지 오차가 발생하지 않는다고 해도, 그 이하부터는 오차가 발생하기 때문에,
오차가 존재하는 double형 변수 둘 이상을 더하다 보면, 소수점 이하 15자리가 아니라,
소수점 이하 셋째 자리에서도 오차가 발생할 수 있다.
따라서 실수의 계산은 기본적으로 오차가 존재한다고 인식해야 한다


Char 자료형

하드웨어가 숫자밖에 인식을 못하니 문자를 숫자로 표현하는 수밖에 없다.
그래서 문자를 숫자로 표현하기 위한 몇몇 표준이 프로그래밍 언어에 상관없이 만들어졌는데,
자바는 이 중에서 유니코드(unicode)라는 표준을 근거로 문자를 표현하고 있다.
유니코드는 문자 하나를 2바이트로 표현하는 문자체계이다.
2바이트로 표현할 수 있는 데이터의 수는 2의 16승 개이므로
총 6만개 이상의 문자표현이 가능하다는 계산이 나온다.
따라서 유니코드는 세계의 모든 언어를 표현할 수 있는 문자체계이다.
문자는 작은 따옴표로 표현이 된다
char형 변수는 문자의 저장을 위해 사용된다.
char형 변수에 실제 저장되는 것은 저장되는 문자의 유니코드 상수 값이다


int num = 1+5

여기서 1+5는 변수의 상대적 개념인 상수(=리터럴)라 부른다.
상수라 부르는 이유는 값이 변경될 수 없기 때문이다
하지만 상수도 메모리 공간에 저장이된다.
CPU를 통해서 연산이 이루어지기 때문이다.
해당 연산의 상수들은 기본자료형으로 표현 및 저장된다
모든 정수형 상수는 int형으로
모든 실수형 상수는 double형으로
그래서 long으로 선언된 자료형에 저장하려고 해도 접미사를 붙여야 하는 것이다
그래서 float로 선언된 자료형에 저장하려고 해도 접미사를 붙여야 하는 것이다
: 자바 컴파일러는 상황에서 값의 크기를 기준으로 판단하지 않고, 값의 표현에 사용되는 바이트 크기를 기준으로 판단을 한다.


자동 형 변환

프로그래머가 별도의 형 변환 명령을 내리지 않아도 형 변환이 발생하는 대표적인 사례
double num1 = 20;
int형 정수 20이 double형 실수 20.0으로 자동 형 변환되어 변수에 저장된다.

하지만 다음의 경우에는 자동으로 형 변환이 발생하지 않는다
int num2 = 20.5; -> 컴파일 에러

이처럼 자바에서는 데이터의 손실이 발생하지 않거나, 발생하더라도 그 손실이 제한적인 경우에만 자동 형 변환을 허용한다.
다음은 자바에서 정의하고 있는 자동 형 변환 규칙이다
byte -> short(or char) -> int -> long -> float ->double


논리 연산자와 Short-Circuit Evaluation(Lazy Evaluation)

가장 빠르게 연산을 진행하기 위한 계산방식
(A) && (B) : A가 false이면 B는 확인하지 않는다
(A) || (B) : A가 true이면 B는 확인하지 않는다


비트 연산자

  • & : 비트단위로 AND 연산을 한다
    • : 비트단위로 OR 연산을 한다*
  • ^ : 비트단위로 XOR 연산을 한다 (서로다르면 1, 같으면 0)
  • ~ : 모든 비트를 반전시켜서 얻은 결과를 반환


비트 쉬프트 연산자

 << : 비트 열을 왼쪽으로 이동<2의 배수의 곱> (ex 2 <<1 = 4, 2 << 2 = 8, 2 << 3 = 16) : 이동에 따른 빈 공간은 0으로 채운다
 >> : 비트 열을 오른쪽으로 이동<2의 배수의 나눗셈> (ex 8 >> 1 = 4, 8 >> 2 = 2) : 이동에 따른 빈 공간은 음수의 경우 1, 양수의 경우 0으로 채운다
 >>> : 피연산자의 비트 열을 오른쪽으로 이동


자바의 이름규칙

기본적으로 Camel Convention
상수는 대문자, 두단어 이상의 합성어는 _를 포함


클래스 패스의 지정

패스는 경로의 의미를 지닌다.
클래스 패스는 “클래스의 경로(클래스가 존재하는 경로)”를 뜻한다.
자바 가상머신은 프로그램의 실행과정에서 실행에 필요한 클래스를 찾을 때, 바로 이 클래스 패스를 기준으로 찾게 된다


자바에서 패키지를 분리하는 이유

  • 여러 팀간의 같은 Naming으로 인한 충돌을 방지하기 위해
  • 소스파일들의 경계에 의미를 부여
  • 패키지간의 의존관계를 확인하기 위해 (접근제어를 분리하기 위해)


자바의 지시자

지시자 클래스 내부 동일 패키지 상속받은 클래스 이외의 영역
private O X X X
default O O X X
protected O O O X
public O O O O
 기타 지시자
      final
           변경할 수 없음을 의미
           클래스, 내부 클래스, 메소드, 변수에 선언 가능
           클래스에 선언하면 다른 클래스가 이 클래스를 상속할 수 없음
           메소드에 선언하면 다른 클래스에서 이 메소드를 오버라이딩 할 수 없음
           변수에 선언하면 일단 값이 할당된 이후에는 더 이상 값을 변경할 수 없음
      abstract
           메소드 몸체를 가질 수 없음
           메소드의 몸체를 하위 클래스에서 정의하게 하고 싶을 때 사용하는 제한자
           abstract가 선언된 메소드를 추상 메소드라고 한다
           추상 메소드를 포함한 클래스는 반드시 abstract로 선언해야 하며 이를 추상 클래스라 한다
           추상 클래스를 사용하기 위해서는 상속해서 미구현 메소드를 구현해야 한다
      static  
           메소드나 변수를 메모리에 로딩해서 다른 클래스가 이 클래스의 인스턴스를 생성하지 않고도 사용할 수 있게 해준다
           내부 클래스, 메소드, 변수에 선언 가능
           인스턴스 또는 클래스명으로 접근가능
      native
           다른 언어로 작성된 메소드를 자바에서 사용하기 위해 선언하는 제한자
           메소드에만 선언 가능
           메소드 몸체를 가질 수 없다
      synchronized
           하나 이상의 스레드가 코드의 특정 블록을 동시에 접근하는 것을 제어하기 위해 사용
           메소드와 블록에 선언가능
      transient (JPA는 @Transient이지만, 이것은 자바의 예약어으로 transient int age와 같이 사용한다)
           직렬화 객체 데이터 중 일부의 데이터를 여러가지 이유로 전송하고 싶지 않을 경우,
           이러한 변수는 직렬화에서 제외해야 되며, 이를 위해서 변수에 transient를 선언한다
      volatile
           http://thswave.github.io/java/2015/03/08/java-volatile.html
           http://kwanseob.blogspot.kr/2012/08/java-volatile.html
           최적화(reordering) 방지 및 멀티스레드 환경에서 데이터캐쉬가 일어나지 않도록 하는것 
           (항상 메인메모리에서 읽도록, 최신의 값을 가져오도록)
           즉 보통 공유되는 static 데이터에 적합


자바의 클래스 제어 지시자

 접근제어자의 종류
      public
           ex : public class A{}
           소스파일의 이름과 일치해야 한다

      default (접근제어자 선언 X) : 
           ex : class A{}
           동일한 패키지 내에서만 접근이 가능하다

 기타 제어자의 종류
      static
           메소드나 변수를 메모리에 로딩해서 다른 클래스가 
           이 클래스의 인스턴스를 생성하지 않고도 사용할 수 있게 해준다     
           내부 클래스에서 사용가능
      final
           다른 클래스에서 이 클래스를 상속받을 수 없음
      abstract
           하위 클래스에서 abstract method를 구현하게끔 강제

 테스트
      public class A 에 public 생성자 - 다른패키지에서 import 가능, 접근가능
      class A 에 public 생성자 - 다른패키지에서 import 불가
      public class A 에 default 생성자 - 다른패키지에서 import 가능, 접근불가


자바 콘솔입력

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
int num = Integer.parseInt(str);

Scanner sc = new Scanner(System.in)
int num = sc.nextInt(); //nextLine() -> String 반환


객체 관계

is a (상속)
has a (복합관계)


직렬화 (Serializable)

데이터를 파일에 쓰거나, 네트워크를 타고 다른 곳에 전송할 때는 데이터를 바이트 단위로 분해하여 순차적으로 보내야 한다. 이것을 직렬화(Serialization)라고 한다.
기본 자료형은 정해진 바이트의 변수이기 대문에 바이트 단위로 분해하여 전송한 후 다시 조립하는데 문제가 없다.
하지만 객체의 크기는 가변적이며, 객체를 구성하는 자료형들의 종류와 수에 따라 객체의 크기는 다양하게 바뀔 수 있다.
이런 객체를 직렬화 하기 위해서 Serializable 인터페이스를 구현하게 된다


직렬화가 가능한 객체의 조건

  • 기본형 타입
  • Serializable 인터페이스를 구현한 객체여야 한다.
  • 해당 객체의 멤버들 중에 Serializable 인터페이스가 구현되지 않은게 존재하면 안된다
  • transient가 사용된 멤버는 전송되지 않는다
  • 객체 직렬화는 객체에 implements Serializable만 선언해 주면 된다


자바 가상머신의 메모리 모델

 메모리 분류방식
      메소드 (method area)
           : 메소드의 바이트코드 -> 프로그램의 흐름을 구성하는 바이트 코드, 
             사실상 컴파일 된 바이트코드의 대부분이기 때문에, 전체 바이트코드가 올라간다고 봐도 무리가 없다, 
             당연히 static 메소드도 포함된다
           : static 변수

      스택 (stack area)
           : 지역변수
           : 매개변수

      힙 (heap area)
           : 인스턴스


Object 클래스

finalize 메소드 : 인스턴스가 소멸되기 직전에 자바 가상머신에 의해서 자동으로 호출되는 메소드, 그러나 호출보장이 안된다 (gc타이밍은 예측불가. gc가 동작해도 인스턴스의 완전한 소멸은 유보될 수 있기 때문에, 그래서 공식처럼 System.gc(); System.runFinalization()을 쓴다는데 이런짓 하지마라)

equals 메소드 : 동일성, 동등성 ( == 로 비교하는건 무조건 동등성, equals는 기본적으로 동등성 비교인데 오버라이드해서 동일성비교하도록 한다)

copy
1. shallow copy : reference를 복사 -> Clonable Interface 참조
2. deep copy : 새로운 reference를 생성해서 참조한다 -> Clonable Interface 참조, clone 메서드를 오버라이딩해서 직접구현


Wrapper 클래스

기본 자료형 데이터를 인스턴스화 시키는 작업을 가리켜 Boxing이라고 한다 (오토박싱, 오토언박싱)


난수생성

사실상 컴퓨터에게 난수를 생성하도록 요구하는 것은 사실상 불가능에 가깝다.
그래서 컴퓨터가 생성하는 난수를 가리켜 “Pseudo-random number”라 하는데, 이는 “가짜 난수”라는 뜻이다.
그래서 Seed값을 설정한다. Seed값이 같으면 동일한 결과와 순서로 출력한다.
System.currentTimeMille()같이 유닉스타임 값을 씨드로 많이 사용한다. (default도 이렇게 되있음)


제네릭

 제네릭은 “일반화”한다는 뜻을 담고 있다. 그리고 그 일반화의 대상은 자료형이다
 Object를 써도 되잖아?
      컴파일 과정에서 발견되는 오류를 검출할 수 있다
      자료형에 대한 안전성이 보장된다
      상황에 따라서 둘 이상의 클래스를 정의할 수 있다

 정의방법
      클래스에 대한 제네릭 정의 class<T>
      메서드에 대한 정의 방법 public <T> void test(T t), public <T, Y> void test(T t, Y y)

 제네릭 매개변수에 대한 제한조건 : <T extends (Interface or Upperclass)>
 제네릭 변수의 와일드카드 선언
      와일드 카드란 이름 또는 문자열에 제한을 가하지 않음을 명시하는 용도로 사용되는 특별한 기호
      파일의 이름을 명시하는데 *가 와일드카드로 사용되었다.
      이렇듯 자바는클래스의 이름을 명시하는데 있어서 와일드카드로 사용되는 기호 ?를 정의하고 있다. 
      그리고 이를 기반으로 다음과 같이 변수 또는 매개변수가 선언될 수 있도록 하고 있다
      FroutBox<? extends Fruit> box1 = new FruitBox<Fruit>();
      이것은 매개변수에 제네릭객체를 선언함에 있어 유용하다.


자바 Collection

 컬렌션 프레임워크의 인터페이스 구조
      Collection<E> : iterable 인터페이스를 상속한다. iterator라는 이름의 메소드가 정의되어 있다 : “컬렉션 클래스의 종류에 상관없이 동일한 형태의 데이터 참조방식을 유지한다” : 오름차순을 보장
           Set<E>
           List<E>
           Queue<E>
           Map<K, V>


 List
      : 동일한 인스턴스의 중복 저장을 허용한다.
      : 인스턴스의 저장 순서가 유지된다
      ArrayList (배열과 비슷, 하지만 자동용량 증가 등의 편이성)
           저장소의 용량을 늘리는 과정에서 많은 시간이 소요된다 (선형자료구조)
           데이터의 삭제에 필요한 연산과정이 매우 길다 (뒤에 저장된 데이터들을 한 칸씩 앞으로 이동)
           데이터의 참조가 용이해서 빠른 참조가 가능하다
      LinkedList (비선형 자료구조)
           저장소의 용량을 늘리는 과정이 간단하다
           데이터의 삭제가 매우 간단하다
           데이터의 참조가 다소 불편하다

 Set<E> : 수학에서 말하는 “집합”의 특성을 가진다
      : List<E>를 구현하는 클래스들과 달리 Set<E>를 구현하는 클래스들은 데이터의 저장순서를 유지하지 않는다.
      : List<E>를 구현하는 클래스들과 달리 Set<E>를 구현하는 클래스들은 데이터의 중복저장을 허용하지 않는다
      HashSet<E>
           객체를 담을때에는 동등비교를 equals 메소드의 호출결과와 hashCode 메소드의 호출결과를 가지고 한다
           매우 빠른 검색속도 -> 매우 빠른 저장속도
      TreeSet<E>
           트리 자료구조를 기반으로 구현되어 있는데, “트리”는 데이터를 정렬된 상태로 저장하는 자료구조이다.
           따라서 이를 기반으로 구현된 TreeSet<E> 클래스 역시 데이터를 정렬된 상태로 유지한다
           객체의 경우, Comparable 을 구현해야지 자료구조를 이용할 수 있다

 Map<K, V>
      HashMap<K, V>
           Hash 알고리즘 사용, 매우 빠른 검색속도
           value에 상관없이 중복된 Key의 저장은 불가능하다
           value는 같더라도 key가 다르면 둘 이상의 데이터 저장도 가능하다
      TreeMap<K, V>
           NavigableSet set = treeMap.navigableKeySet();
           set.iterator() : 오름차순
           set.descendingIterator() : 내림차순


자바의 쓰레드 생성법

 Thread를 상속
 Runnable Interface 구현

 동기화
      Synchronized 키워드
      동기화 메서드보다 동기화 블록이 효율적이다.
           다중 Synchronized 메서드의 경우? 동기화의 의미가 퇴색될 수 있다. 이럴경우 블록이 효과적.
           관계없는 코드까지 동기화할필요가 없다

 실행순서의 동기화
      Object 클래스에 정의된 메서드를 이용
           NewsReader 사용자 스레드는 getTodayNews() 메서드를 선언,
           오늘뉴스가 도착했는지 확인해서 false면 wait()한다.
           NewPapaer에서 setTodayNews 메서드를 호출, 메서드안에서 notifyAll() 호출

           하단의 메서드들은 민감한 메서드들이므로 모두 동기화 블록처리해서 실행한다
           wait() // 기다린다
           notify() // 하나의 쓰레드만 깨운다
           notifyAll() //모든 스레드를 깨운다.


JDBC API_1. Statement

정적 SQL 문을 실행 해, 작성된 결과를 돌려주기 위해 사용하는 객체이다.
기본적으로, Statement 객체 당 하나의 ResultSet 객체가 동시에 열릴 수 있다(사용될 수 있다).
그러므로 하나의 ResultSet 오브젝트의 읽기가 다른 read에 의해 끼어 들어지면,
각각은 다른 Statement 객체에 의해 생성되어 있어야 한다.
만약 열려있는(사용중인) Statement의 ResultSet이 있다면 암시적으로 닫힐 수 있다
(이 말은 ResultSet을 닫으면 Statement객체 또한 암시적으로 자원해제 될 수 있다는 의미인것 같다)

생각정리 : Statement 객체는 Escape의 기능이없다. 매 요청마다 새로운 Query를 만들어서 실행하는 방식인것이고,
매번 동적으로 바뀌는 부분을 “select 데이터 from table where id =”+숫자와 같이 스트링을 더하는 형태로
만들 수 밖에 없다. 이렇게 생성되는 쿼리는 매 요청마다 새로 만들어지는 것이다
또한 Statement 방식은 유저의 입력 String을 그대로 사용하는 경우가 많으므로 SQL Injection의 위험이 있으므로 사용하지 않는게 좋다

다음은 API에 정의된 원문 내용이다

public interface Statement extends Wrapper, AutoCloseable
The object used for executing a static SQL statement and returning the results it produces.
By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects. All execution methods in the Statement interface implicitly close a statment’s current ResultSet object if an open one exists.


JDBC API_2. PreparedStatement

프리 컴파일 된 SQL 문을 나타내는 객체이다.
SQL 문은 프리 컴파일 해, PreparedStatement 객체에 저장된다.
문장을 여러 차례 효율적으로 실행하기 위해 사용될 수있다.

다음은 API에 정의된 원문 내용이다

public interface PreparedStatement extends Statement
An object that represents a precompiled SQL statement.
A SQL statement is precompiled and stored in a PreparedStatement object.
This object can then be used to efficiently execute this statement multiple times.

Note: The setter methods (setShort, setString, and so on) for setting IN parameter values must specify types that are compatible with the defined SQL type of the input parameter.
For instance, if the IN parameter has SQL type INTEGER, then the method setInt should be used.

If arbitrary parameter type conversions are required, the method setObject should be used with a target SQL type.

In the following example of setting a parameter, con represents an active connection:

PreparedStatement pstmt 
  = con.prepareStatement("UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)


JDBC API_3. CallableStatement

스토어드 프로시저 SQL을 실행하기 위한 인터페이스.
일반적인 RDBMS을 호출하는 방식과 동일하게 escape 문법을 사용할 수 있다.
프로시저 호출결과에 대한 결과값을 가져오기 위해서는 OUT Parameter로 result Parameter를 설정해야 한다.
일반적인 파라미터는 IN, OUT Parameter를 구분없이 사용할 수 있다. 첫번째 파라미터는 1로 설정된다

다음은 API에 정의된 원문 내용이다

public interface CallableStatement extends PreparedStatement
The interface used to execute SQL stored procedures. The JDBC API provides a stored procedure SQL escape syntax that allows stored procedures to be called in a standard way for all RDBMSs. This escape syntax has one form that includes a result parameter and one that does not. If used, the result parameter must be registered as an OUT parameter. The other parameters can be used for input, output or both. Parameters are referred to sequentially, by number, with the first parameter being 1.
{?= call [(,, ...)]}
{call [(,, ...)]} IN parameter values are set using the set methods inherited from PreparedStatement. The type of all OUT parameters must be registered prior to executing the stored procedure; their values are retrieved after execution via the get methods provided here.

A CallableStatement can return one ResultSet object or multiple ResultSet objects. Multiple ResultSet objects are handled using operations inherited from Statement.

For maximum portability, a call's ResultSet objects and update counts should be processed prior to getting the values of output parameters.


JVM

Reference : http://stophyun.tistory.com/37
Reference : http://huelet.tistory.com/entry/JVM-메모리구조

왜 JVM을 이해해야 하는가?

정보시스템의 설계 및 개발단계의 오류로 인한 성능 저하 문제가 약 33% (설계오류, 아키텍처 오류, 어플리케이션 코드 오류)를 차지하고 있으며 특히, 설계 또는 아키텍처의 오류는 개선에 따르는 비용과 시간이 타 부분에 비하여 막대하므로 정보시스템 구축 시 프로젝트 전 단계에 걸쳐 지속적으로 성능관리를 수행하고 그 결과를 검증하는 것이 중요하다.
같은 기능의 프로그램이더라도 메모리 관리에 따라 성능이 다르게 나타난다
속도저하 현상이나 예기치않은 에러 현상 등을 방지
한정된 메모리를 효율적으로 사용하여 최고의 성능을 제공

JVM 정의 및 특징

자바 가상 머신 (JVM; Java Virtual Machine)은 우리가 작성한 Java 프로그램, WAS (;Web Application Server) 등을 구별하지 않고 Java 프로그램의 범주에 들어가는 모든 것들을 실행시키는 역할을 한다.
JVM은 정의된 Specification을 구현한 하나의 독자적인 Runtime Instance라고 할 수 있다.

특징1. 스택기반의 가상머신
특징2. 가비지 컬렉션
특징3. 플랫폼에 독립적

JVM의 기본적인 수행과정

Java Source(.java) - Java Compiler - Java Byte Code(.class) - JVM

JVM 구성

  • Class Loader
  • Runtime Data Areas
  • Execution Engine
  1. Class Loader System을 통해 Class 파일들을 JVM으로 로딩한다
  2. 로딩된 Class 파일들은 Execution Engine을 통해 해석된다
  3. 해석된 프로그램은 Runtime Data Areas에 배치되어 실질적인 수행이 이루어지게 된다.
    이러한 실행 과정 속에서 JVM은 필요에 따라 Thread Synchronization과 Garbage Collection 같은 관리작업을 수행하게 된다

Class Loader

JVM 안으로 Class를 Load하고 Link를 통해 적절히 배치하는 일력의 작업을 수행하는 모듈. Runtime시에 동적으로 Class를 Load함

Execution Engine

클래스 로더를 통해 JVM 내의 런타임 데이터 영역에 배치된 바이트코드는 실행 엔진에 의해 실행된다. 실행엔진은 자바 바이트코드를 명령어 단위로 읽어서 실행한다

Runtime Data Area

JVM이라는 프로그램이 운영체제 위에서 실행되면서 할당받는 메모리 영역이다. 런타임 데이터 영역은 5개의 영역으로 나눌 수 있다

1.Class Area (클래스)

Method Area, Code Area, Static Area로 불리어진다
모든 스레드가 공유되는 영역으로 JVM이 시작될 때 생성된다

1-1. Field Information : 멤버변수의 이름, 데이터 타입, 접근 제어자에 대한 정보
1-2. Method Information : 메서드의 이름, 리턴타입, 매개변수, 접근 제어자에 대한 정보
1-3. Type Information : Type 속성이 Class인지 Interface인지의 여부저장
- Type의 전체이름 (패키지명 + 클래스명)
- Type의 Super Class의 전체이름
- 접근 제어자 및 연관된 interface의 전체 리스트 저장
1-4. Constant Pool
- Type에서 사용된 상수를 저장하는 곳(중복이 있을 시 기존상수 사용)
- Type에서 사용된 상수를 저장하는 곳(중복이 있을 시 기존상수 사용)
1-5.Class Variable : 모든 객체가 공유할 수 있고, 객체 생성없이 접근 가능

2.Stack Area (스택)

- JVM 스택은 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 생성된다. 스택 프레임(Stack Frame)이라는 구조체를 저장하는 스택으로, JVM 스택에 스택 프레임을 추가하고(push) 제거하는(pop) 동작만 수행한다
- 메서드 안에서 사용되어지는 값들 저장, 호출된 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장
- 메서드 수행이 끝나면 프레임별로 삭제

3.Heap Area (힙)

new 연산자로 생성된 객체와 배열을 저장하는 공간

클래스 영역에 로드된 클래스만 생성가능

Garbage Collector를 통해 메모리 반환 JVM 성능 등의 이슈에서 가장 많이 언급되는 공간이다

3-1. Permanent Generation : 생성된 객체들의 정보의 주소 값이 저장된 공간
3-2. Young Generation (New Area)
- Eden : 객체들이 최초로 생성되는 공간
- Survivor : Eden에서 참조되는 객체들이 저장되는 공간
3-3. Old Generationr (Old Area) : New Area에서 일정시간 이상 참조되고 있는 객체들이 저장되는 공간

4.Native Method Stack Area (네이티브 메서드)

  • 자바 외에 다른 언어에서 제공되는 메서드들이 저장되는 공간

  • Java 외의 언어로 작성된 프로그램, API 툴킷 등과의 통합을 쉽게 하기 위하여 JNI (Java Native Interface)라는 표준 규약을 제공, 다시 말해 Native Code로 되어 있는 Function의 호출을 Java 프로그램 내에서 직접 수행할 수도 있고 그 결과 값을 받아 올 수도 있게 된 것이다.

5.PC Register (PC 레지스터)

Thread가 만들어질 때마다 생성되는 공간

Thread가 어떤 부분을 어떤 명령으로 실행할 지에 대한 기록

현재 실행되는 부분의 명령과 주소를 저장


Garbage Collection

참조되지 않은 객체들을 탐색 후 삭제
삭제된 객체의 메모리를 반환
Heap 메모리의 재사용

  • Minor Garbage Collection
    • New 영역에서 일어나는 Garbage Collection
    • Eden 영역에 객체가 가득차게 되면 첫번째 Garbage Collection 발생
    • Survivor1 영역에 값 복사
    • Survivor1 영역을 제외한 나머지 영역의 객체들을 삭제
    • Eden 영역과 Survivor1 영역의 메모리가 기준치 이상일 경우, Eden 영역에 생성된 객체와 Survivor1 영역에 있는 객체 중 참조되고 있는 객체가 있는지 검사
    • Survivor2 영역을 제외한 영역의 객체들을 삭제
    • 반복
  • Major Garbage Collection (Full Garbage Collection, Stop the world)
    • Old 영역에 있는 모든 객체들을 검사
    • 참조되지 않은 객체들을 한꺼번에 삭제
    • Minor Garbage Collection에 비해 시간이 오래 걸리고 실행 중 프로세스가 정지