1. 자바(Java Programming Language)
1.1 자바란?
- 객체지향 프로그래밍 언어
- 절차지향 언어 : C언어
- 객체지향 언어: Java, Python, C## 등등...
- 객체지향 프로그래밍의 반대 개념이 절차지향 프로그래밍은 아님. 프로그래밍 접근 방식이 다를 뿐...
- 정확하게는 객체지향 프로그래밍과 절차적 프로그래밍이 정확함(자바로도 절차적으로 코딩이 가능)

- 정리하자면 OO지향이란 코딩하는 방식 또는 방법론의 차이이지 특정 언어가 특정지향만 지원한다는 것은 아니라는 것
1. 캡슐화, 다형성, 클래스 상속을 지원하는가?
2. 데이터 접근 제한을 걸 수 있는가?
보통은 위 기준을 만족하면 객체지향, 만족하지 않으면 절차적 성격이 강해짐
- 절차적 프로그래밍에 흐름도

데이터에 대한 순서를 파악하고 필요한 기능을 함수로 만들어 절차적으로 진행시킴
- 객체지향 프로그래밍의 예시

- 두 가지 순서도 비교

https://st-lab.tistory.com/151
객체지향(OOP)과 절차적 프로그래밍(PP)
오늘은 프로그래밍에서 중요한 개념 중 하나인 객체지향 프로그래밍(Object Oriented Programming)과 절차적 프로그래밍(Procedure Programming)에 대해 알아보고자 합니다. 대개 객체지향 프로그래밍 언어를
st-lab.tistory.com
- 운영체제에 독립적
- 풍부한 라이브러리들을 제공
1.2 자바의 역사
- 1991년 6월 제임스 고슬링에 의해 만들어짐
- "Write Once, Run Anywhere"을 약속
- 2009년 오라클과 인수 합병됨
1.3 자바언어의 특징
1. 운영체제에 독립적이다.
이것은 JVM을 통해서 가능하게 됨.
자바 응용프로그램은 JVM하고만 통신, JVM은 전달받은 명령을 해당 운영체제가 이해할 수 있도록 변환하여 전달.
각 운영체제에 맞는 JVM이 있어서 썬에서는 여러 운영체제에 설치할 수 있는 서로 다른 버전의 JVM을 제공

2. 객체지향언어이다.
- 객체지향언어의 특징
- 추상화(abstraction)
- 객체들의 공통적인 특징(기능, 속성)을 도출하는 것
- 객체지향적 관점에서는 클래스를 정의하는 것을 추상화라고 할 수 있다.(클래스가 없는 객체지향 언어도 존재 ex.JavaScript)
- 캡슐화(encapsulation)
- 실제로 구현되는 부분을 외부에 드러나지 않도록 하여 정보를 은닉할 수 있다.
- 객체가 독립적으로 역할을 할 수 있도록 데이터와 기능을 하나로 묶어 관리하는 것(멤버변수, 메서드)
- 코드가 묶여있어서 오류가 없어 편리하다.
- 데이터를 보이지 않고 외부와 상호작용을 할 때는 메소드를 이용하여 통신을 한다. 보통 라이브러리로 만들어서 업그레이드해 사용할 수 있다.(접근 제어, public ,private )
- 상속성(inheritance)
- 하나의 클래스가 가진 특징(함수, 데이터)을 다른 클래스가 그대로 물려받는 것(extends)
- 이미 작성된 클래스를 받아서 새로운 클래스를 생성하는 것
- 기존 코드를 재활용해서 사용함으로써 객체지향 방법의 중요한 기능 중 하나에 속한다.
- 다형성(polymorphism)
- 약간 다른 방법으로 동작하는 함수를 동일한 이름으로 호출하는 것
- 동일한 명령의 해석을 연결된 객체에 의존하는 것
- 오버라이딩(Overriding), 오버로딩(Overloading)
- 오버라이딩(Overriding) - 부모클래스의 메소드와 같은 이름을 사용하며 매개변수도 같되 내부 소스를 재정의하는 것(extends)
- 오버로딩(Overloading) - 같은 이름의 함수를 여러 개 정의한 후 매개변수를 다르게 하여 같은 이름을 경우에 따라 호출하여 사용하는 것
- 동적바인딩(Dynamic Binding)
- 가상 함수를 호출하는 코드를 컴파일할 때, 바인딩을 실행시간에 결정하는 것.
- 파생 클래스의 객체에 대해, 기본 클래스의 포인터로 가상 함수가 호출될 때 일어난다.
- 함수를 호출하면 동적 바인딩을 통해 파생 클래스에 오버라이딩 된 함수가 실행
- 프로그래밍의 유연성을 높여주며 파생 클래스에서 재정의한 함수의 호출을 보장(다형 개념 실현)


3. 비교적 배우기 쉽다.
- 간결하고 명료한 객체지향적 설계를 통해 사용자들이 쉽게 이용하고 활용할 수 있게 됨.
4. 자동 메모리 관리(Garbage Collection)
- 자동적으로 메모리를 관리해주는 가비지컬렉터가 있음
Garbage Collection , GC 는 JVM 상에서 더 이상 사용되지 않는 데이터가 할당되어있는 메모리를 해제시켜주는 장치입니다. JVM 에서 자동으로 동작하기 때문에 Java 는 특별한 경우가 아니면 메모리 관리를 개발자가 직접 해줄 필요가 없습니다. GC 가 주로 동작하는 대상은 Heap 영역 내의 객체 중에서 참조되지 않은 데이터입니다. 예시로 코드와 함께 학습해보겠습니다.

위에서 person은 처음에 “a” 라는 이름을 가진 객체를 참조하게 됩니다. 하지만 곧 이어 person이 “b” 를 참조하게 되며 “a”는 다음 줄에서 참조를 잃어버리게 됩니다. main 함수가 종료되기 직전, person이 가르키는 객체가 “b”를 가르킨 직후에 GC 가 이루어진다고 가정해봅시다. “b” 는 참조가 유지된 상태이기 때문에 GC 의 대상이 아니지만, “a” 는 GC 의 대상이 됩니다. 위의 경우처럼 참조하는 대상을 바꾸거나 메소드가 끝나서 Stack 이 pop 이 되면 참조되지 않는 객체들이 생겨납니다.
참조되고 있는지에 대한 개념을 reachability 라고 하고, 유효한 참조를 reachable , 참조되지 않으면 unreachable 이라고 합니다. 그리고 GC 는 unreachable 한 객체들을 garbage 라고 인식하게 됩니다. 다음은 Heap 영역에서 reachable , unreachable 한 개념들을 도식화하였습니다.

GC 실행 알고리즘을 공부하기 전에 추가로 알아야 할 개념이 있습니다. 바로 Stop-The-World 라는 개념입니다. JVM 은 GC 를 통해 JVM 에서의 여유 메모리를 확보할 수가 있습니다. 이 때문에 GC 를 자주 실행시키면, 여유 메모리를 최대한 확보하여 성능이 좋아지리라 추측할 수도 있습니다. 하지만 빈번한 GC 는 프로그램의 성능을 저하하게 됩니다. GC 가 일어나면 GC 를 담당하는 쓰레드를 제외한 모든 쓰레드들은 작동이 일시적으로 정지되게 됩니다. 이를 Stop-The-World 현상이라고 합니다. 모든 쓰레드가 정지되기 때문에 더 이상 작업이 실행되지 않고, 성능이 저하됩니다. 그래서 적절한 빈도의 GC 가 실행되도록 하여, Stop-The-World 시간을 줄여 쓰레드가 정지되는 시간을 줄이는 것이 중요합니다.
https://tecoble.techcourse.co.kr/post/2021-08-30-jvm-gc/
JVM에 관하여 - Part 4, Garbage Collection 기초
Java 로 작성된 코드는 어떻게 돌아가는 걸까? 해당 물음에 답을 찾기 위한 JVM 시리즈 4편, JVM 의 구성요소 중 GC 에 관한 글입니다. 이번 글에서는 JVM 의 GC 에 대한 기초 지식에 대해서 알아봅시다.
tecoble.techcourse.co.kr
런타임시 stack 영영과 heap 영역이 활성화 되는데, 메서드 호출이 끝나면 다 어차피 없어지는게 아닌가????
5. 네트워크와 분산처리를 지원한다.
- 풍부하고 다양한 라이브러리를 통해 네트워크 관련 프로그램을 쉽게 개발할 수 있도록 지원
6. 멀티쓰레드를 지원한다.
- 시스템과 관계없이 구현가능
- 쓰레드에 대한 스케줄링을 자바 인터프리터가 담당
멀티 쓰레드와 멀티 프로세스
우선 멀티 쓰레드와스레드와 멀티 프로세스에 대해서 간략하게 확인하고 가자. 멀티 스레드와 멀티 프로세스에 대해서 혼란스러워하는 경우가 있는데 둘은 다른 기능을 의미한다. 멀티 스레드는 하나의 프로세스에서 여러 개의 작업을 하도록 해주는 기능이며, 멀티 프로세스는 여러 개의 프로세스를 사용하여 병렬적 일 처리를 할 수 있게끔 해주는 기능을 의미한다. 아래의 그림을 참고하면 이해하기 훨씬 쉬울 것이다.

Java에서 Thread를 구현하는 방법은 두가지가 있다. 하나는 Thread 클래스를 이용하는 것이고 하나는 Runnable 인터페이스를 이용하는 것이다.
1) Thread Class
먼저 Thread Class를 이용하는 방법은 아래와 같다.
(a) Thread Class를 상속 받은 Class를 하나 만듦
(b) run() 메서드를 overriding하여 수행할 일을 코딩해준다.
(c) main thread 에서 a 단계에서 만든 Class의 start() 메서드를 호출한다.
여기서 start() 는 run() 안에 정의된 일을 main 스레드가 아닌 별도로 만들어진 thread에서 처리한다는 것이니 꼭 해줘야한다.
간단하게 예시를 하나 들어서 코드로 구현해보겠다.


2) Runnable Interface
다음은 Runnable 인터페이스를 이용하는 방법이다.
(a) Runnable Interface를 구현하는 Class를 하나 만듦
(b) run() 메서드를 overriding하여 수행할 일을 코딩해준다.
(c) 구현된 인터페이스를 스레드 생성시 생성자 파라미터로 넣어준다.
(d) main thread 에서 a 단계에서 만든 Class의 start() 메서드를 호출한다.

7. 동적 로딩을 지원
- 실행 시에 모든 클래스가 로딩되지 않고 필요한 시점에 클래스를 로딩하여 사용할 수 있음
1.4 JVM(Java Virtual Machine)
- 자바를 실행하기 위한 가상 컴퓨터.
- Java 애플리케이션은 OS와 하드웨어에 독립적
- JVM은 OS에 종속적이기 때문에 각 OS에 맞는 JVM이 필요


1. Method area (메소드 영역)
클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보같은 필드 정보와 메소드의 이름, 리턴 타입, 파라미터, 접근 제어자 정보같은 메소드 정보, Type정보(Interface인지 class인지), Constant Pool(상수 풀 : 문자 상수, 타입, 필드, 객체 참조가 저장됨), static 변수, final class 변수등이 생성되는 영역이다.
2. Heap area (힙 영역)
new 키워드로 생성된 객체와 배열이 생성되는 영역이다.
메소드 영역에 로드된 클래스만 생성이 가능하고 Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.
3. Stack area (스택 영역)
지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값등이 생성되는 영역이다.
int a = 10; 이라는 소스를 작성했다면 정수값이 할당될 수 있는 메모리공간을 a라고 잡아두고 그 메모리 영역에 값이 10이 들어간다. 즉, 스택에 메모리에 이름이 a라고 붙여주고 값이 10인 메모리 공간을 만든다.
클래스 Person p = new Person(); 이라는 소스를 작성했다면 Person p는 스택 영역에 생성되고 new로 생성된 Person 클래스의 인스턴스는 힙 영역에 생성된다.
그리고 스택영역에 생성된 p의 값으로 힙 영역의 주소값을 가지고 있다. 즉, 스택 영역에 생성된 p가 힙 영역에 생성된 객체를 가리키고(참조하고) 있는 것이다.
메소드를 호출할 때마다 개별적으로 스택이 생성된다.
4. PC Register (PC 레지스터)
Thread(쓰레드)가 생성될 때마다 생성되는 영역으로 Program Counter 즉, 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다. (*CPU의 레지스터와 다름)
이것을 이용해서 쓰레드를 돌아가면서 수행할 수 있게 한다.
5. Native method stack
자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역이다.
보통 C/C++등의 코드를 수행하기 위한 스택이다. (JNI)
쓰레드가 생성되었을 때 기준으로
1,2번인 메소드 영역과 힙 영역을 모든 쓰레드가 공유하고,
3,4,5번인 스택 영역과 PC 레지스터, Native method stack은 각각의 쓰레드마다 생성되고 공유되지 않는다.
Static
Java에서 Static 키워드를 사용한다는 것은 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 것을 의미합니다.
이를 정확히 이해하기 위해서는 메모리 영역에 대한 이해가 필요합니다.
일반적으로 우리가 만든 Class는 Static 영역에 생성되고, new 연산을 통해 생성한 객체는 Heap영역에 생성됩니다.
객체의 생성시에 할당된 Heap영역의 메모리는 Garbage Collector를 통해 수시로 관리를 받습니다.
하지만 Static 키워드를 통해 Static 영역에 할당된 메모리는 모든 객체가 공유하는 메모리라는 장점을 지니지만,
Garbage Collector의 관리 영역 밖에 존재하므로 Static을 자주 사용하면 프로그램의 종료시까지 메모리가 할당된 채로 존재하므로 자주 사용하게 되면 시스템의 퍼포먼스에 악영향을 주게 됩니다.
(1) Class Loader
JVM 내로 클래스 파일을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈입니다. 런타임 시에 동적으로 클래스를 로드합니다.
(2) Execution Engine
클래스 로더를 통해 JVM 내의 Runtime Data Area에 배치된 바이트 코드들을 명렁어 단위로 읽어서 실행합니다. 최초 JVM이 나왔을 당시에는 인터프리터 방식이었기때문에 속도가 느리다는 단점이 있었지만 JIT 컴파일러 방식을 통해 이 점을 보완하였습니다. JIT는 바이트 코드를 어셈블러 같은 네이티브 코드로 바꿈으로써 실행이 빠르지만 역시 변환하는데 비용이 발생하였습니다. 이 같은 이유로 JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고, 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일러 방식으로 실행합니다.
(3) Garbage Collector
Garbage Collector(GC)는 힙 메모리 영역에 생성된 객체들 중에서 참조되지 않은 객체들을 탐색 후 제거하는 역할을 합니다. 이때, GC가 역할을 하는 시간은 언제인지 정확히 알 수 없습니다.
(4) Runtime Data Area
JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역입니다. 이 영역은 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 나눌 수 있습니다.