본문 바로가기
ComputerScience/Languages

[프로그래밍언어] 자바(1) 비 언어적 부분( 구성, 특성 )

by Develaniper 2021. 6. 2.

자바 카테고리와는 달리 자바의 특성만을 요약하여 다루는 포스팅입니다.

1. JDK, JRE, JVM

1) JDK(Java Development Kit)

 JDK는 JVM과 JRE 분만아니라 자바를 사용해서 개발을 하기위한 도구가 포함되어 있는 kit이라고 보면 될거 같다. 대표적으로 자바 컴파일러가 이에 포함되고 개발자가 아니라면 사용할 일이 없는 도구이다.

2) JRE(Java Runtime Environment)

 Java를 실행하기 위해서 필요한 도구로 JVM을 포함하고 있다. JRE에는 JVM을 실행하며 필요한 라이브러리들과 바이트코드(.class파일)를 JVM에 올리는 클래스 로더가 있다.

3)JVM(Java Virtual Machine)

 자바 코드가 최종적으로 실행되는 가상머신이다. 자세한 내용은 아래에서 다룬다.

2. JVM(Java Virtual Machine)

자바 가상머신이라는 뜻으로 자바 어플리케이션을 읽어 실행하는 역할을 한다. 자바는 어느 운영체제에서든지 실행이 가능한데 그 이유는 JVM이 JAVA와 OS 사이의 중개자 역할을 하여 OS에 구애받지 않고 실행 할 수 있기 때문이다.

또한, 메모리관리GarbageCollection(GC)을 수행한다.

 

1) JVM의 원리가 중요한 이유

 메모리 효율성을 위해 메모리 구조를 이해할 필요가 있기 때문에

 

2) 자바 실행과정

  1. 프로그램이 실행되면 JVM은 OS로부터 필요한 메모리를 할당받는다.
     이 메모리를 JVM이 용도에 따라 여러 영역으로 관리한다.
  2. 자바 컴파일러(javac)가 자바코드(.java)를 읽어 바이트코드(.class)로 변환(컴파일)시킨다.
  3. Class Loader를 통해 class파일들을 JVM으로 로딩한다.
  4. 로딩된 class 파일들은 Excution Engine을 통해 해석(인터프리트)된다./ 적절한 시점에 JIT에 의해 컴파일 됨
  5. 해석된 바이트코드는 Runtime Data Areas에 배치되어 실행된다.
    JVM은 필요에 따라 GarbageCollection, Thread Synchronization같은 관리작업을 한다.

3) JVM 구성요소

[1] Execution Engine(실행엔진)
  •  클래스 로더가 바이트코드(.class)를  JVM의 런타임 데이터 영역(Runtime Data Area)에 로딩하면 실행엔진이 실행하기 시작한다. 자바의 바이트코드는 기계가 바로 실행할 수 있는 언어이기보다 사람이 보기 편한 형태로 기술되어있어 실행엔진은 이를 기계친화적 언어로 변경하는 역할을 한다.
  •  또한, 코드 실행에는 시스템 리소스에 대한 액세스 관리가 포함되어있는데 파일, 네트워크, 메모리 리소스 요구 프로그램과 OS의 가운데에서 이런 리소스를 공급하는 역할을 한다.
  •  실행엔진은 인터프리터와 JIT 컴파일러 방식을 이용하여 프로그램을 실행한다.
[2] Interpreter(인터프리터)
  •  자바 바이트 코드를 명령어 단위로 읽어 실행한다. 하지만 인터프리터 언어의 특성상 상대적으로 느리다는 단점을 가지고 있다.
[3] JIT(Just In Time)
  •  인터프리터 방식의 단점을 보완하기 위해 도입된 컴파일러로 인터프리터 방식을 실행하다가 적절한 시점에 바이트 코드 전체를 네이티브 코드(기계가 실행할 수 있는 언어)로 컴파일하고 이후에는 네이티브 코드만 사용하는 방식이다.
  • 네이티브 코드는 캐시에 보관하여 한번 컴파일된 코드는 빠르게 수행 할 수 있다.
  • 다만 컴파일 과정은 인터프리트 과정보다 오래걸리므로 JVM내부적으로 메서드의 수행빈도를 체크하여 일정 수준을 넘는 코드에 대해서만 컴파일을 수행한다.
[4] GC(Garbage Collector)
  • 가비지 컬렉션은 메모리를 관리하는 프로세스로 자바 프로그램에서 사용되지 않는 메모리를 지속적으로 찾아내 제거하는 역할을 한다.
  •  자바 이전에는 프로그래머가 메모리를 관리했었지만, 자바에서는 JVM이 메모리를 관리한다.
  • 초기에는 속도 측면에서 많은 비평을 받았지만 다양한 알고리즘과 접근방식의 제안으로 크게 개선되었다.
[5] Runtime Data Area

  1. PC레지스터
    • Thread가 생성될 때마다 생성되는 영역으로(각 쓰레드는 하나의 PC레지스터를 갖는다.) 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역
    • PC가 있기 때문에 다수의 쓰레드가 명령의 흐름을 유지할 수 있다.
  2. JVM 스택
    • 프로그램 실행과정에서 임시로 할당 되었다가 메서드를 빠져나가면 소멸되는 데이터를 저장하기 위한 영역이다.
    • 메서드에서 사용하는 임시데이터(변수 혹은 계산 중간값), 스레드나 메서드의 정보를 저장한다.
    • 스택이 동작하는 예는 다음 영상에서 참조 가능 ([10분 테코톡] 🎅무민의 JVM Stack & Heap)
  3. Native method stack
    •  자바프로그램이 컴파일된 바이트코드(.class)가 아니라 실제 실행을 하는 기계어로 작성된 프로그램을 실행 시키는 영역으로 JAVA 이외의 언어에서 제공되는 Method의 정보가 저장된다.
    • 즉, 자바 프로그램에서 필요한 Native의 Method들이 저장되는 공간으로 이 부분을 통해 kernel에 접근할 수 있다.
    • JNI(JAVA Native Interface)를 통해 호출되는 C/ C++등의 코드가 저장된다.
  4. Method Area(Class area, Static area)
    • 클래스에서 필요한 패키지클래스, 런타임 상수pool, 인터페이스, 상수, static 변수, final 변수, 클래스 멤버변수 등의 필드데이터와 생성자를 포함한 모든 메서드의 정보 등이 로드된 후 항상 상주하는 영역.
    • 모든 스레드에서 공유 가능하다.
    • 올라가는 정보
      필드 정보 : 멤버변수 이름, 데이터 타입, 접근제어자
      메서드 정보 : 메서드 이름, 리턴타입, 매개변수, 접근제어자
      타입 정보 : class인지 interface인지 여부, Type의 속성, 전체 이름, super class의 전체이름
  5. Heap(힙 영역)
    • new를 통해 동적으로 생성되는 객체, 배열 등의 값이 저장되는 영역이다.
    • Heap영역에 있는 객체들은 JVM 스택에서 참조가능한데, 만일 객체를 사용하지 않는다면 Garbage Collector에 의해 제거된다.
-Heap영역(세부사항)

Heap은 효율적인 GC를 위해 다음과 같은 영역으로 나뉘어 집니다. GC는 크게 Minor GC와 Major GC로 나뉩니다.

우선 각 영역에대한 설명이다.

  • Permanent Generation
     생성된 객체들의 정보의 주소값이 저장되는 공간으로, Class loader에 의해 로드되는 클래스, 메서드 등에 대한 메타 정보가 저장되는 영역이고 JVM에 의해 사용된다. Java8 부터는 Native Memory영역으로 이동했다.
  • Tenured(Old) Generation
     New 영역에서 일정시간 참조되고 있는, 살아남은 객체들이 저장되는 공간으로 Eden영역에 객체가 가득 차게 되면 첫번째 GC가 발생한다.
     Eden 영역에 있는 값들을 Survivor 1 영역에 복사하고 이 영역을 제외한 나머지 영역의 객체를 삭제한다.
  • Young(New) Generation
    이 영역은 Eden과 Survivor영역으로 나뉜다.
    - Eden : 객체들이 최초로 생성되는 공간
    - Survivor 0/1 :  Eden에서 참조되는 객체들이 저장되는 공간

4) Garbage Collection

[1] Minor GC가 일어나는 과정
  1. new를 통해 다양한 객체 생성 중 Eden 영역이 가득 차게되면 첫 GC가 일어난다.
  2. Eden에서 참조되지 않은 객체를 제거하고 참조가 유지되는 객체를 S0으로 이동시킨다.
  3. 계속하여 객체 생성 중 Eden영역이 가득차게 되면 참조를 유지하는 객체를 S1로 이동 시킨다.
    이때 S1에서 참조가 유지되는 객체도 S1로 이동시키고 age를 1더한다.
  4. 이런 식으로 Eden -> S0 -> S1 -> S0 ... 을 반복하며 Minor GC가 일어난다.
[2]  Major GC(Full GC)가 일어나는 과정
  1. Minor GC가 일어나는 중 객체의 age가 증가하여 오래 살아남게 되면 어느정도 오래 살아남은 객체를 Old영역으로 옮긴다.
  2. Old영역의 모든 객체를 검사하고 참조되고 있는지 확인 하고 참조가 되지 않는다면 한번에 이들을 모아 제거한다.
  3. 이를 Major GC라고 부르며 Full GC라고도 한다.
  4. 이때, Full GC를 제외한 모든 쓰레드가 중지되어야 한다.
[3] GC를 하는 이유
  •  자바 객체의 2가지 특징으로 인해 객체의 생명주기를 직접 관리하여 불필요한 객체를 메모리에서 해제시키려고 함.
    1. 대부분의 객체는 금방 접근 불가능 상태가 됨(Unreachable)
    2. 오래된 객체에서 젊은 객체로의 참조는 아주 적다.
    3. Heap 인스턴스 중 Thread의  JVM 스택에 도달할 수 없는 것들을 GC의 대상으로 삼는다.
  • 도달할 수 없는 것을 선택하여 삭제하는것이 아니라 도달할 수 있는 것들을 선택한 후 나머지를 삭제한다.(Mark and Sweep)

3. 자바 프로그래밍

1) OOP(Object Oriented Programming)

[1]SOLID
[2] 6가지 키워드
  1. 클래스
  2. 인스턴스
  3. 추상화
  4. 캡슐화
  5. 상속
  6. 다형성

2)AOP(Aspect Oriented Programming)

3) FP(Fuctional Programming)

 

4. 버전별 특징

1) JAVA 7

  • Type Inference(타입 추론)
  • Switch문 문자열 case
  • Automatic Resource Management
  • Catching Multiple Exception Type in Single Catch Block

2) JAVA 8 (오라클 인수 후 첫번째 버전)

  • GC 성능 개선
    - 기본 GC -> Parallel GC(여러개의 쓰레드)
  • Lambda Expression
  • interface 클래스에 구현체 작성가능
    - default, static이용하여 기본 구현체 작성 가능
  • Optional
    - null이 될 수도 있는 객체를 감싸는 일종의 래퍼 클래스
  • 새로운 날짜와 시간 API
    - (LocalDate, LocalTime, LocalDateTime)
  • Stream API
  • Repeating Annotation

2) JAVA 9

  • JAVA를 인터프리터 언어 셀처럼 사용할 수 있는 JShell 추가
  • 모듈 시스템 등장
  • private 인터페이스 메서드
  • immutable collection
  • 64비트 버전만 출시
  • 프로퍼티 파일에 UTF-8 지원

3) JAVA 10

  • var 키워드를 이용한 지역변수 타입 추론
  • 개별 쓰레드로 분리된 Stop-The-World
  • 루트 CA 목록

 

 

5. Value vs Reference

1) 기본형, 참조형 변수

 자바의 변수타입은 기본형과 참조형이 있다.

  1. 기본형
    • boolean, char, byte, short, int, long, float, double
    • 위의 8개의 변수만 기본형 변수에 해당한다.
    • 메서드의 파라미터로 넘겨 메서드에서 그 값을 변경하더라도 값의 변화가 없다.
  2. 참조형
    • 기본형을 제외한 모든 변수 타입으로, 객체의 주소를 저장한다.
    • 기본형과 반대로 파라미터로 넘겨 메서드에서 그 값(멤버변수 값)을 변경하면 메서드가 끝난 후 값이 변경되어있다.

자세한 내용은 필자의 포스트를 참조바란다.

2021.05.08 - [개발/JAVA] - [JAVA 개념] 변수, 배열

2) call By Value vs call By Reference ?

그럼 자바는 call By Value와 call By Reference중 어느 쪽에 해당할까?

기본변수는 call By Value이고 참조형은 call By Reference?

결론적으로 답은 call By Value가 맞다.

위와 같이 Call By Value로 동작하기 때문에 method에서 sc값을 변경해도 값이 1로 유지된다.

 

자바는 참조객체(자체)가 저장된 주소값을 넘겨준다. Call by Reference가 되려면 변수가 저장된 주소를 넘겨주고 new를 통해 새로운 인스턴스를 대입한다면 그 주소자체에 새로운 인스턴스로 변경 되지만, 자바의 경우 주소를 넘겨준 것이라 sc는 지역변수로써 method안에서만 다른 인스턴스로 할당받고 쓰이는 것이다.

 

즉, Call By Value와 Call By Reference를 결정하는 것은 주소(참조형)를 넘겨주느냐 아니냐가 아니라 변수의 주소값을 넘겨주고 그 변수의 주소에 저장된 값 자체를 바꿀 수 있느냐 아니냐의 문제인 것이다.

 

확인은 해당 블로그를 참고 바란다. (https://develaniper-devpage.tistory.com/60)

 

 

6. 자바를 사용하는 이유(C/C++등 과 비교하여)

  1. 메모리관리
    • 자바는 free나 delete를 사용하지 않고 가비지컬렉션이 메모리를 관리해 줘서 개발에만 집중할 수 있다.
  2. Write Once Run Anywhere
    • 자바의 대표적인 특징으로 플랫폼에 구애받지않고 JVM을 통해 동작함으로 어디서나 작동할 수 있다.
  3. 멀티쓰레드를 쉽게 구현 가능
    • Thread를 사용하는 것은 매우 복잡한 일이다. 특히 환경에 따라 사용법이 다르기 때문에 매우 까다롭다. 하지만 자바는 JVM을 이용하여 같은 코드를 사용하여 쉽게 쓰레드를 구현할 수 있다.

 

 

 

참조

(JVM)
https://asfirstalways.tistory.com/158
https://www.itworld.co.kr/news/110837
https://velog.io/@jsj3282/JVM과-자바-메모리-구조Runtime-Data-Area
https://honbabzone.com/java/java-jvm/
( 자바 버전)
https://kudl.tistory.com/entry/JAVA-버전별-특징
https://ggomi.github.io/jdk-version/
(Call By Value, Reference)
http://wonwoo.ml/index.php/post/1679

 

 

댓글