6 minute read




자바언어의 탄생과 발전

자바의 탄생과 발전

(1) 자바의 탄생 (1991년)
그린 프로젝트(Green Project)에서 시작
Sun Microsystems제임스 고슬링(James Gosling) 주도
가전제품용 소프트웨어 개발을 목적으로 연구 시작

(2) 자바(Java) 공개 (1995년)
• 1995년 ‘Java’ 공식 발표
• 최초의 이름: 오크(OAK) → 이후 자바(Java)로 개명
• 공개 당시 웹 브라우저 Netscape에서 실행

(3) 자바의 발전
• 1995년 인터넷과 웹의 발전과 함께 주목받기 시작
• 2009년 Sun Microsystems가 오라클(Oracle)에 인수
• 현재까지 광범위한 분야(웹, 모바일, 서버, IoT)에서 사용


자바의 개발 목적

(1) C 언어의 포인터(pointer) 문제 해결
(2) 플랫폼 호환성 문제 해결
• 기존 언어는 PC, 유닉스, 메인프레임 간 호환성이 부족
• 소스를 다시 컴파일하거나 프로그램을 재작성해야 함
(3) 플랫폼 독립적인 언어 개발
• 모든 플랫폼에서 호환성을 갖는 프로그래밍 언어 필요
• 특히 네트워크, 웹에 최적화 된 언어!
(4)메모리 사용량이 적고, 다양한 가전제품에 적용
• 내장형 시스템(Embedded System) 요구 충족
• 가전제품: 작은 양의 메모리를 가지는 제어장치




자바언어의 특징

자바의 플랫폼 독립성

(1) WORA (Write Once, Run Anywhere)

한 번 작성된 코드가 모든 플랫폼에서 바로 실행 가능하다

• 기존 언어(C/C++)의 플랫폼 종속성 문제를 극복
• OS(운영체제), H/W(하드웨어)에 상관없이 동일한 실행 환경 제공
• 네트워크에 연결된 어느 클라이언트에서나 실행: 웹 브라우저, 분산 환경 지원

(2) WORA를 가능하게 하는 자바의 특징
[ 바이트코드 (Bytecode) ]
• 자바 소스를 컴파일하여 생성된 목적 코드
• 특정 CPU에 종속되지 않은 중립적인 코드
JVM(Java Virtual Machine)에 의해 해석되고 실행가능한 이진(binary) 코드
[ 자바 가상 머신 (JVM - Java Virtual Machine) ]
바이트코드를 실행하는 가상 기계(소프트웨어)
• 운영체제(OS)와 독립적으로 동작
각 플랫폼(OS)별로 JVM만 설치하면 자바 프로그램 실행 가능

(3) 객체지향 언어




자바 배포판


오라클은 개발 환경에 따라 다양한 자바 베포판 제공

[ Java SE ]
• 자바 표준 베포판(Standard Edition)
• 데스크탑과 서버 응용 개발 플랫폼

[ Java ME ]
• 자바 마이크로 베포판 (Micro Edition)
• 휴대전화나 PDA, 셋톱박스 등 성능/자원이 제한적인 하드웨어 응용 개발을 위한 플랫폼
• 가장작은메모리필요
• JavaSE의 일부 + 임베디드 시스템 및 가전제품을 위한 API 정의

[ Java EE ]
• 자바 기업용 베포판 (Enterprise Edition)
• 자바를 이용한 다중 사용자, 기업용 응용 개발을 위한 플랫폼
• JavaSE + 인터넷 기반의 서버 사이드 컴퓨팅관련 API 추가




자바 개발도구

JVM < JRE < JDK 의 포함관계를 가진다

[ JVM (Java Virtual Machine) - 자바 가상 머신 ]
• 자바 바이트코드를 실행하는 소프트웨어
• 모든 (HW)플랫 폼에 설치: 플랫폼마다 다른 JVM이 존재하지만, 동일한 실행 환경 제공
• JVM 자체는 플랫폼에 종속적, 다양한 회사에서 공급
• JVM은 바이트코드를 해석하여 CPU가 실행할 수 있는 기계어로 변환

단계 역할
클래스 로딩 .class 파일을 JVM에 로드
바이트코드 검증 코드의 안정성 검사
실행 (인터프리터 & JIT) 바이트코드를 CPU가 이해하는 기계어로 변환
가비지 컬렉션(GC) 더 이상 사용되지 않는 객체 제거

바이트코드(Bytecode)란?
• 자바 소스를 컴파일한 결과물(완전한 기계어가 아닌 중간단계의 코드)
• 특정 CPU에 종속되지 않는 중립적인 코드
• JVM에 의해 해석되고 실행되며, .class 파일에 저장됨
• 모든 운영체제에서 동일한 실행 환경 제공
• 자바 가상 기계가 해석하는(인터프리터) 방식으로 바이트 코드 실행
• 자바 가상 기계가 작동준인 플랫폼에서 실행

[ JRE (Java Runtime Environment) - 자바 실행 환경 ]
• 자바 프로그램을 실행하기 위한 환경
• JVM과 자바 API(라이브러리)들이 들어있는 모듈파일
• 개발자가 아닌 일반 사용자는 JRE만 설치하면 자바 프로그램 실행 가능

[ JDK (Java Development Kit) - 자바 개발 키트 ]
• 자바 애플리케이션을 개발하고 실행할 수 있는 도구 모음
• JDK는 JRE와 추가적인 개발 도구(컴파일러, 디버거 등)를 포함
• 자바 코드를 작성하고 실행하려면 반드시 JDK가 필요
• 표준판(SE), 기업판(EE)
• JDK의 bin/파일함(directory, folder)에 포함된 주요 개발 도구

개발 도구 역할
javac 자바소스를 바이트코드로 변환하는 컴파일러
java 자바 응용프로그램 실행기, 자바 가상 기계를 작동시켜 자바프로그램을 실행
javadoc 자바 소스로부터 HTML 형식의 API 문서(document) 작성
jar 자바 클래스들(패키지포함)을 압축한 자바 아카이브 파일(.jar) 작성 관리
jmod 자바의 모듈 파일(.jmod)을 만들거나 모듈 파일의 내용 출력
jlink 응용프로그램에 맞춘 맞춤형(custom) JRE 제공
jdb 자바 응용프로그램의 실행 중 오류를 찾는 데 사용하는 디버거
javap 클래스 파일의 바이트 코드를 소스와 함께 보여주는 디어셈블러




자바 실행과정

자바 실행환경

[실행 환경]

자바가상기계 + 자바 플랫폼의 클래스 라이브러리(자바 API)

[응용프로그램 실행]
main() 함수(method)를 가진 classmain()에서 시작
• JVM이 필요할 때 클래스 파일을 탑재함: 적은 메모리로 실행가능


자바와 C/C++의 실행방식 차이

비교 Java C/C++
  자바원시파일(-.java)
컴파일러
바이트코드(-.class)
하드웨어 - 운영체제 - JVM - 자바프로그램
C 원시파일(-.cpp)
컴파일러/링커
바이너리 실행 파일(-.exe)
하드웨어 - 운영체제 - C/C++ 프로그램



자바 실행과정

(1) 소스 코드 작성

개발자가 .java 파일을 작성한다

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}


(2) 컴파일 (javac)

작성된 소스 코드는 javac(Java Compiler)에 의해 바이트코드로 변환된다
• 컴파일 후 Hello.class 파일이 생성
• 이 파일은 CPU가 직접 실행할 수 없는 바이트코드로 이루어져 있음

javac Hello.java


(3) 클래스 로딩 (JVM이 .class 파일 로드)
• JVM의 Class Loader.class 파일을 메모리에 적재
• 필요한 클래스들을 동적으로 로딩하여 실행


(4) 실행 (JVM이 바이트코드 해석)
인터프리터(Interpreter) 방식으로 바이트코드를 한 줄씩 해석하며 실행
• 또는 JIT(Just-In-Time) 컴파일러를 통해 기계어로 변환하여 성능 최적화
• 최종적으로 CPU가 실행

java Hello

출력:

Hello, Java!


(6) 프로그램 종료

프로그램 종료 시, JVM이 사용한 메모리를 해제하고 실행을 종료



자바 실행 과정의 핵심 흐름

.java (소스 코드)       
   ↓ [javac 컴파일]
.class (바이트코드)
   ↓ [JVM 실행]
CPU에서 실행 (Machine Code)




자바의 프로그램 구조

자바 프로그램은 클래스(Class) → 메서드(Method) → 문장(Statement) 으로 구성된다

[ A.java ]
// 1. 패키지 선언  (필수는 아님)
package mypackage;

// 2. 클래스 선언
public class A {

    // 3. main 메서드 (프로그램의 시작점)
    public static void main(String[] args) {
        
        // 4. 변수 선언 및 초기화
        int number = 10;  
        
        // 5. 메서드 호출
        printMessage(number);
    }

    // 6. 사용자 정의 메서드 (기능 정의)
    public static void printMessage(int num) {
        System.out.println("입력된 숫자: " + num);
    }
}




JDK와 메모리 영역

JVM(Java Virtual Machine)은 자바 프로그램을 실행하기 위해 여러 개의 메모리 영역(5개)을 관리한다

메서드(Method) 영역 (또는 클래스 영역)
힙(Heap) 영역
스택(Stack) 영역
PC 레지스터(Program Counter Register)
네이티브 메서드 스택(Native Method Stack)


JVM 메모리 영역의 종류

메서드 영역 (Method Area)

클래스 메타데이터를 저장하는 공간

• JVM이 로드한 클래스 정보, 정적(static) 변수, 상수, 메서드 코드, 인터페이스 정보 등이 저장됨
• 모든 스레드(Thread)가 공유하는 영역
런타임 상수 풀(Runtime Constant Pool) 포함 → 상수(리터럴, 상수 문자열) 저장

class Example {
    static int staticVar = 10; // 메서드 영역에 저장
}


[ 힙 영역 (Heap Area) ]

객체(인스턴스)와 배열이 저장되는 공간

new 키워드를 사용해 생성한 객체가 저장됨
가비지 컬렉션(GC, Garbage Collection)에 의해 관리됨
• 모든 스레드가 공유하는 영역

class Example {
    int instanceVar = 20; // 힙 영역에 저장
}

public class Main {
    public static void main(String[] args) {
        Example obj = new Example(); // obj는 힙 영역에 저장
    }
}


[ 스택(Stack) 영역 ]

각 메서드 호출 시 생성되는 메모리 영역

• 메서드 실행에 필요한 지역 변수, 매개변수, 연산 중간값, 리턴 값 등이 저장됨
• 메서드 호출 시 새로운 스택 프레임(Stack Frame)이 생성되고, 메서드가 종료되면 제거됨
스레드별로 개별적으로 존재 (스레드마다 하나의 스택을 가짐)

public class Main {
    public static void main(String[] args) {
        int num = 10; // 스택 영역에 저장
        add(num); // add 메서드 호출 -> 새로운 스택 프레임 생성
    }

    public static void add(int x) {
        int result = x + 5; // 스택 영역에 저장
    }
}


[ PC 레지스터 (Program Counter Register) ]

JVM이 실행 중인 명령어 주소(현재 실행 중인 바이트코드 위치)를 저장하는 공간

• 스레드마다 하나씩 존재 → 각 스레드가 실행할 명령어의 위치를 추적
자바 바이트코드 명령어를 순차적으로 실행할 때 사용됨


[ 네이티브 메서드 스택 (Native Method Stack) ]

C, C++과 같은 네이티브 코드(C언어 기반 라이브러리)를 실행할 때 사용되는 스택

JNI(Java Native Interface)를 통해 실행되는 네이티브 메서드 호출 시 사용됨
• 예를 들어, JNI를 사용하여 C++ 메서드를 호출할 때 사용됨

public class Example {
    public native void nativeMethod(); // 네이티브 메서드 선언
}



JVM 메모리 구조 요약

메모리 영역 역할 특징
메서드 영역 (Method Area) 클래스 정보, static 변수, 메서드 코드 저장 모든 스레드가 공유
힙 영역 (Heap Area) new로 생성한 객체 저장 모든 스레드가 공유, GC 관리
스택 영역 (Stack Area) 지역 변수, 메서드 호출 정보 저장 스레드별 개별 생성
PC 레지스터 (PC Register) 현재 실행 중인 명령어 주소 저장 스레드별 개별 존재
네이티브 메서드 스택 (Native Stack) 네이티브 코드(C, C++) 실행 JNI 호출 시 사용



JVM 메모리 관리 - 가비지 컬렉션(GC)

• JVM은 힙 영역의 불필요한 객체를 자동으로 제거(Garbage Collection)
• GC는 더 이상 참조되지 않는 객체를 탐색하여 메모리를 해제
System.gc();를 호출하여 GC 실행 요청 가능하지만, 보장되지 않음

Example obj1 = new Example();
Example obj2 = new Example();
obj1 = null; // obj1이 참조하는 객체는 GC 대상