Java 목적
- Write Once Use Anywhere(한 번 작성하면 어디서든 실행 가능)
- JVM설치 시 운영체제(OS) MacOS, Window, Linux등 어느곳에서든 실행 가능
- Android는 JVM 사용하지 않기 때문에 변환 필요 : .jar(Java 실행파일)이나 .class(Java 바이트코드)를 .apk(안드로이드 앱 실행 파일)로 변환 필요
- iOS에서도 JVM 사용불가(지원 안함)하기 때문에 실행 불가하나, J2ObjC, RoboVM 등 사용해서 Java코드를 iOS에서 지원하는 코드로 변환 가능함.
- 소스코드를 바이트 코드(반기계어(.class))로 컴파일 해주는 것이 자바 컴파일러(javac)
프로세스(Process)란?
프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 의미, 프로그램에 사용되는 메모리 자원과 스레드로 구성
스레드(thread)란?
프로세스 내부에서 실제로 작업을 수행하고 있는 주체, 2개 이상의 스레드를 가지고 있는 프로세스는 멀티 프로세스(multi-threaded process)라고 함.
Reflection이란?
객체를 통해 클래스의 정보를 분석해 내는 프로그래밍 기법, 구체적인 클래스 타입을 알지 못해도 컴파일된 바이트 코드를 통해 역으로 클래스 정보를 알아내어 사용가능
C언어 목적
- One Source Multi Object Use Anywhere(하나의 소스로 여러 개의 실행 파일을 만들어 사용)
- 같은 C 코드(.c)라도 Windows용 실행 파일(.exe)과 Linux용 실행 파일(.out)을 따로 만들어야 함.
- Windows, Linux, macOS에서는 C 코드를 직접 실행 파일로 만들 수 있음.
- Android, iOS에서도 C 코드로 실행 파일을 만들 수 있지만, 추가적인 과정(NDK, Xcode)이 필요.
- C 코드만으로는 Android/iOS 앱을 만들 수 없고, Java/Kotlin(iOS는 Swift/Objective-C)과 연동해야 함.
자바코드 실행 구조
소스코드(.java) -> Java 컴파일러(javac) -> 바이트 코드(.class) -> JVM(Class Loader : 동적 로딩, 실행에 필요한 클래스 로딩 후 JVM 내부 Runtime Data Area에 로드) -> JVM(Execution에 의해 기계어로 해석되어 실행)
전처리과정
JRE는 메인 메서드 포함여부를 확인 후 JVM을 부팅 하고, 부팅 된 JVM은 전달받은 코드를 실행 시키는데, 이때 가장 먼저 하는 작업이 전처리과정임.
1. 모든 Java프로그램은 java.lang 패키지를 포함 하는데 JRE는 해당 패키지를 Method area에 배치 함
2. import한 추가 패키지들도 Method area에 배치
3. 클래스, 변수 및 메서드 등의 정보도 Method area에 배치
Class Loader
모든 클래스, 변수, 메서드의 정보를 Method Area에 배치
JVM 내부에 바이트 코드를 로드하고 링크를 통해 배치하는 작업을 수행하는 모듈
* 링크 : 클래스가 실행될 수 있도록 필요한 검증(1. 검증 : JVM에서 실행할 수 있는 올바른 바이트코드인지 확인), 2 준비 : static(정적) 변수들의 메모리를 할당하고 기본값으로 초기화, 3 해석 : 다른 클래스, 메서드, 변수 등을 참조하는 부분을 실제 메모리 주소로 변경)과 배치 작업을 수행하는 과정
실행될 때 동적으로 클래스를 로드하고 jar 파일 내부에 저장되어 있는 클래스들을 JVM에 로드
**“동적 로드”**란 프로그램 실행 중에 필요한 클래스를 메모리에 올리는 것을 의미 (ex : Java, Python, C#), 메모리 절약, 프로그램 실행 중 새로운 기능 추가 및 업데이트 가능
**“정적 로드”**란 컴파일 타임에 모든 클래스를 미리 메모리에 올리는 방식 (ex : C, C++), 빠른 실행 속도(운영체제 자체 핵심 프로그램), 의존성 명확하게 관리 필요 시(임베디드 시스템(자동차, 가전제품 등)의 펌웨어, 배포 환경이 제한적일 때(군사용 시스템), 보안이 중요한 경우(금융 시스템)
Runtime Data Areas
JVM의 메모리 영역
Method Area, Heap Area, Stack Area, PC Registers, Native Method Stack으로 구성.
Metaspace(Method area, Native memory) : static 변수, static 메서드, 클래스 메타정보 (클래스 이름, 부모 클래스 정보 등)
* Runtime constant pool : 클래스 생성할 때 참조해야 할 정보들을 상수로 가지고 있는 영역.(상수 자료형 저장 및 참조, 중복 방지)
* JVM실행 시 생성되는 공간, 바이트 코드(.class)를 처음 메모리 공간에 올릴 때 초기화 되는 대상을 저장하기 위한 공간(프로그램이 종료될 때까지 저장)
* Native Memory : Metaspace, JNI(Java Native Interface) 관련 메모리, JIT 컴파일러의 코드 캐싱 영역으로 구성
* JNI : 다른 언어로 만들어진 어플리케이션과 상호 작용할 수 있는 인터페이스를 제공
Heap Area : 객체(인스턴스) 저장 공간(new로 생성된 객체, 인스턴스 변수), 런타임 시 동적으로 할당하여 사용하는 메모리 영역, GC에 의한 메모리 관리, 모든 스레드가 공유
* Permanent generation : 생성된 객체 정보의 주소값이 저장되는 공간, Java 8 이후 Heap영역에서 제거되고, Native 메모리 영역에 저장 됨. 즉, Heap이 아니라 OS가 직접 관리하는 메모리 영역(Native 메모리)에 저장됨(이전에 제한된 메모리 크기 때문에 발생했던 한계점을 극복하기 위해 변경)
* New/Young generation : Eden(객체들이 최초 생성되는 공간), Survivor 0, 1(Eden에서 참조되는 객체들이 저장되는 공간), 생명 주기가 짧은 객체를 Garbage Collector의 대상으로 하는 영역, Eden영역이 가득차면 Garbage Collector에 의해 Eden에 있는 값들을 Survivor 1 영역에 복사하고 이 영역을 제외한 나머지 객체들을 삭제 함.
📌 Survivor 0(S0), Survivor 1(S1)의 역할
1. 객체가 생성되면 Eden에 저장됨.
2. Eden이 가득 차면 GC(Young GC)가 실행됨.
3. Eden에서 살아남은 객체는 Survivor 0(S0)으로 이동.
4. 다음번 GC 실행 시, S0에 있는 객체는 Survivor 1(S1)로 이동.
5. 이 과정을 반복하다가 일정 횟수 이상 살아남으면 Old(Tenured) 영역으로 이동.
* Tenured Generation : Old(이곳 객체들은 Garbage Collector에 의해 삭제 됨), New/Young Generation에 의해 일정시간 참조되고 있고 살아남은 객체들이 저장되는 공간, 생명 주기가 긴 객체를 Garbage Collector의 대상으로 하는 영역.
Stack Area : 메서드 실행을 위한 공간(임시 데이터 저장)(지역 변수, 매개변수, 연산 중 발생하는 임시 데이터, 메서드 호출 정보 (스택 프레임)), 선입후출(FILO) 구조, 메모리 자동 관리(메서드 종료 시 자동 제거), 각 스레드별 존재
* 가장 처음 실행되는 메서드(main())가 첫 번째로 메모리에 올라가고 그 다음에 실행되는 메서드들이 위에 쌓이는 구조
* 쌓이는 메서드의 단위를 스택 프레임이라고 함. 메서드 수행이 끝나면 프레임별로 삭제가 됨.
* 멀티스레드 환경에서 각 스레드가 고유의 스택 영역을 가짐
PC Registers : 스레드 시작 시 생성되는 공간, 현재 실행 중인 JVM 명령 주소(어떤 명령에 의해 실행되어야 하는지에 대한 기록), CPU명령어(Instruction) 수행.
Native Method Stack Area : 자바 외 언어(ex : C, C++, 기계어)로 작성된 네이티브 코드를 위한 메모리 또는 기계어로 작성된 프로그램을 실행시키는 영역

* Interpreter 언어 : 한 줄씩 코드를 해석하고 즉시 실행하는 방식(Python, JavaScript, Ruby)
* Compile 언어 : 전체 코드를 미리 기계어로 변환한 후 실행하는 방식(C, C++, Rust)
* 컴파일 : 프로그래밍 언어로 작성된 소스 코드(.java, .c 등)를 기계어(바이너리 코드)로 변환하는 과정
* 바이트 코드는 JVM이 읽고 실행하는 코드고, 바이너리 코드는 컴퓨터가 이해 할 수 있는 0과 1로 된 코드로 CPU가 직접 실행할 수 있는 코드를 의미
* 캐싱 : 자주 사용되는 데이터를 빠르게 접근할 수 있도록 저장하는 기술, JIT(Just-In-Time)컴파일러가 바이트코드를 기계어(바이너리 코드)로 변환한 후, 변환된 결과를 저장하는 과정을 캐싱
* JIT(Just-In-Time) 컴파일러는 프로그램 전체를 한 번에 변환하는 게 아니라, 실행 중에 자주 실행되는 특정 코드(핫스팟 코드, Hotspot Code)만 바이너리 코드로 변환해서 캐싱
* 핫스팟 코드 : 반복문(Loop), 자주 호출되는 메서드, 실행 중 최적화 필요 코드(실행 중 코드 패턴을 분석하고 더 빠르게 실행할 수 있는 코드라면 바이너리 코드로 변환시킴)
* 컴파일된 코드를 저장해 두기 때문에 이 코드들은 Interpreter를 통해 실행되는 것이 아니라 바로 실행이 됨, 그렇기 때문에 실행 속도가 빨라짐.
* C언어는 개발자가 직접 메모리를 해제해줘야 함. GC는 일반적으로 자동 실행됨.
JDK(Java Development Kit)
- 코드를 번역하여 컴퓨터가 이해 할 수 있는 바이트 코드로 변환하는 도구인 Java 컴파일러가 포함되어 있음
- JDK는 개발에 필요한 모든 도구(JVM + 컴파일러 + 표준 라이브러리 등)를 포함한 패키지
- JDK에는 JRE가 포함되어 있음
- 일반적으로 OpenJDK + 제조사의 부가기능 으로 구성되며, 대표적인 것이 Oracle JDK(현재 상용버전이여서 라이센스 이슈를 피하기 위해서는 다른 제조사의 JDK 사용 권장)
- JDK 종류가 여러가지인데, 대표적인 OracleJDK는 상용화 목적으로 사용할 경우 유료 결제 필요.( 추가 성능 최적화, GUI 애플리케이션에 대한 추가적인 지원, LTS 버전 제공)
> OpenJDK : 오라클이 관리하는 공식 오픈소스 JDK, 무료, LTS 지원 X
> Amazon Corretto : AWS에서 제공하는 무료 JDK, AWS 환경에 최적화
> Azul Zulu : 장기 지원(LTS) 제공, 상업적 사용 가능, LTS 지원 6년 이상, IoT, 클라우드, 대규모 시스템에 최적화
> Adoptium (Eclipse Temurin) : 안정적이고 기업에서도 많이 사용
LTS : (Long-term Support) : 장기 지원 버전, 후속 버전이 출시되어도 일정 기간 동안 지원을 지속
non-LTS : 지원 X
JRE(Java Runtime Environment), JVM(Java Virtual Machine)
- JRE : JVM + Java 표준 라이브러리(java.util, java.io 등)
- Java로 컴파일된 어플리케이션을 실행하는 역할, 자바 실행 환경
- 모든 Java 어플리케이션은 JVM(바이트코드를 실행하는 가상 머신)이라는 가상 컴퓨터 공간에서 실행되며, 어떤 운영체제라도 JVM이 설치되어 있으면 Java 어플리케이션을 실행할 수 있음.
JDK 설치
- 필자 기준, Mac : VSCODE(Extension Pack for Java 설치) , Azul Zulu JDK(17)설치
- New java project 생성 > No build tools > 프로젝트명 입력
- src > app.java 실행해보기 (Run Java)
* Java 클래스 파일의 이름은 반드시 대문자로 시작
자바 코드의 시작 main 함수
자바로 작성된 코드는 main 함수로 진입한 후 작성된 소스의 작업을 모두 수행하면 main 함수가 종료되며, 이는 곧 프로그램의 종료를 의미합니다.
public class App {
public static void main(String[] args) throws Exception {
System.out.println("Hello, World!");
}
}
System.out.println("Hello, World!"); : 콘솔에 값을 출력하기 위한 Java 함수
;(세미콜론) : 하나의 명령 단위가 끝났다는 의미로 작성 필요
'코딩 > Java' 카테고리의 다른 글
Java 6 : Map, Hash, HashTable (1) | 2025.02.07 |
---|---|
Java 5 : 객체지향(OOP : Object-Oriented-Programming), 추상화, 인터페이스 (0) | 2025.02.06 |
Java 4 : 조건문, 반목문, 배열 (0) | 2025.02.05 |
Java 3 : 연산자 (0) | 2025.02.05 |
Java 2 : 변수 (1) | 2025.02.04 |