자바란

Sirius·2023년 10월 27일

1. 자바 기초

1) 자바는 Cross-Platform의 성질을 가진다.(플랫폼에 독립적)

c는 리눅스나 맥에서 다르게 동작한다.(OS마다 JVM이 다름)

그러나 자바는 자바바이트코트(JB)를 JVM(가상머신)에 보내고 JVM을 통해 다른 환경에서도 똑같이 동작한다.

  • 크로스 플랫폼 : 모든 OS에서 똑같이 동작한다.

2) 왜 Cross-Platform의 성질을 가지는가?(Because JVM)

  • 바이트코드: 자바 컴파일러가 자바 소스 프로그램을 컴파일한 일종의 기계어, JVM에 의해 실행됨(*.class파일)

가. JRE(Java Runtime Environment)
자바실행환경 -> 현지식당임
자바로 짠 코드를 돌릴 컴퓨터에는 JRE라는 것이 설치되어 있어야함
1) JVM
2) 표준라이브러리(요리기초가이드북)

나. JDK(Java Development: 자바 개발 키트)
KitJRE를 포함하는 더 큰 범위
요즘 프로그램은 JDK를 다운받도록 되어있음
1) 컴파일러(번역)
2) 디버거
3) JAR(압축)
4) 프로파일러(모니터링)

  • 실행순서 1
    즉 자바 소스코드(Test.java)를 자바 컴파일러(javac)가 바이트코드(0101000100)로 바꿔서 클래스파일에 저장(Test.class)한다.

  • 실행순서 2
    OS마다 있는 JVM은 사용자가 작성한 클래스 파일을 로딩하여 바이트 코드를 하나씩 실행한다.(인터프리터 방식으로 한 명령씩 해석하고 기계어로 실행 0101011010)

javac는 컴파일 명령어이고(.class파일 생성),
java는 인터프리터 명령어이다.(
.class파일로 각 os 마다의 jvm이 실행)
cp:class path

2. 자바의 특성

1. 플랫폼 독립성

자바는 하드웨어, OS 등 플랫폼에 종속되지 않는 독립적인 바이트 코드로 컴파일된다.
JVM만 있으면 HW/OS를 막론하고 자바프로그램 실행이 가능함

2. 객체지향(OOP)에 최적화

캡슐화, 상속, 다형성 등을 지원함
객체설계, 각 객체의 상호작용 등

3. 클래스로 캡슐화

객체지향언어의 캡슐화 원칙을 철저히 지킨다.
변수나 메소드는 반드시 클래스 내에 구현하도록 한다.
클래스 안에 클래스, 내부클래스를 만들 수 있다.
클래스에 속하지 않은 변수나 메소드는 있을 수 없음

4. 자동 메모리 관리

자바언어는 메모리 할당받는 기능은 있지만, 메모리를 반환하는 기능은 없다.
프로그램내에 사용되지 않는 메모리는 JVM의 가비지 컬렉션 기능에 의해 자동으로 회수됨(개발자의 부담 줄여줌)

5. 그 외 특징

  • 멀티스레드
    하나의 자바프로그램은 다수의 스레드가 동시에 실행할 수 있는 환경을 지원함
    자바는 OS 도움없이 멀티스레드 프로그래밍이 가능함

  • 실행속도개선을 위해 JIT 컴파일러가 사용됨
    JVM이 인터프리터 방식으로 바이트 코드를 실행하므로 C/C++보다 느리다고 알려져있다.
    최근에는 JIT(Just in Time)컴파일러 기법을 이용하여 C/C++와 거의 비슷하도록 개선되었다.
    JIT이란 프로그램을 실행하는 도중 해당 CPU의 기계어 코드를 컴파일하고 CPU가 바로 기계어를 실행하도록 하는 컴파일링 기법이다.

JIT 컴파일러의 작동 방식

  1. 자바 프로그램이 실행되면, JVM은 바이트코드를 해석하여 실행합니다.
  2. 프로그램 실행 중 자주 사용되는 코드 부분(핫스팟이라고 함)을 JIT 컴파일러가 감지합니다.
  3. JIT 컴파일러는 이 핫스팟의 바이트코드를 기계어로 컴파일합니다.
  4. 기계어로 컴파일된 코드는 메모리에 캐싱되어, 후속 실행에서 빠르게 재사용될 수 있습니다.
  5. 결과적으로 프로그램의 실행 속도가 향상됩니다.

즉 자바는 인터프리터 방식과 컴파일 방식이 결합된 형태로 실행된다.
1. 컴파일 단계

  • 소스 코드 → 바이트코드: 자바 소스 코드(.java 파일)는 자바 컴파일러(javac)에 의해 바이트코드(.class 파일)로 컴파일됩니다. 바이트코드는 플랫폼 독립적이며, 어느 자바 가상 머신(JVM)에서나 실행될 수 있습니다.
  1. 실행 단계
  • 바이트코드 → 기계어 (인터프리터 방식): JVM이 바이트코드를 로드하고, 인터프리터를 사용하여 바이트코드를 한 명령어씩 해석하면서 실행합니다.

  • 바이트코드 → 기계어 (JIT 컴파일러 방식): 실행 중에 JVM의 JIT(Just-In-Time) 컴파일러가 바이트코드의 핫스팟(자주 실행되는 부분)을 감지합니다. JIT 컴파일러는 이 핫스팟을 기계어로 컴파일하고, 컴파일된 코드를 캐싱하여 재사용합니다. 이로 인해 프로그램의 실행 속도가 향상됩니다.

따라서 자바는 초기 컴파일 단계에서는 전통적인 컴파일러 방식을 사용하고, 실행 단계에서는 인터프리터와 JIT 컴파일러를 함께 사용하는 형태로 동작합니다. 이러한 접근 방식은 개발의 편의성과 실행 속도의 이점을 모두 제공합니다.

  • 소스와 클래스 파일
    자바소스가 컴파일된 .class파일에는 반드시 하나의 자바 클래스만이 들어있다.
    즉하나의 자바소스파일에 여러개의 클래스를 작성한 경우, 컴파일하면 클래스마다 별도의 클래스 파일이 생성된다.

A.java

public class A{
	class B{
    }
    class C{
    }
  }

-> A.class(바이트코드), B.class(바이트코드), C.class(바이트코드)

3. 자바의 데이터타입

  • primitive 데이터는 스택에 저장됨
    이 데이터는 스택 메모리에 직접 저장된다. 이를 "집"에 비유할 수 있다. 즉, 필요한 모든 정보(예: 숫자 10, 참/거짓 등)를 직접 그 공간 안에 보관한다.

  • non-primitive데이터는 실제데이터가 저장된 주소를 가리킴 따라서 힙에 저장됨
    클래스는 non-primitive데이터여서 힙에 저장됨 참조 타입의 데이터는 힙 메모리에 저장된다. 하지만, 그 데이터를 가리키는 "주소"는 스택 메모리에 저장된다. 이것을 "집 주소"에 비유할 수 있다.(주소:스택 -> 진짜데이터:힙)

4. 타입변환 (Automatic Implicit Casting & Explicit Casting)

  • Automatic Implicit Casting

작은 데이터 유형을 큰 데이터 유형에 할당(char -> int) : 자동으로 변환된다.

  • Explicit Casting

큰 데이터 유형을 작은 데이터 유형에 할당(int -> char) : 데이터 손실의 위험이 있고, (type)와 같은 변환의 유형을 지정해주어야 한다.

5. JAVA에서 + 연산자

자바에서 + 연산자는 두 가지 주요 기능을 가지고 있다.
1) 덧셈 연산
2) 문자열 연결 연산
이 연산자의 기능은 사용되는 피연산자(operands)의 타입에 따라 달라진다.

1) 모든 피연산자가 숫자일 경우: 덧셈 연산

만약 + 연산자의 양쪽에 있는 모든 피연산자가 숫자 타입(int, float, double 등)일 경우, 자바는 이를 덧셈 연산으로 처리한다.
ex: int result = 5 + 3;에서 result 변수에는 8이 저장된다.

2) 두 피연산자 중 하나라도 문자열일 경우: 문자열 연결 연산

만약 + 연산자의 양쪽 중 하나라도 문자열(String)이면, 자바는 덧셈 연산 대신 문자열 연결 연산을 수행한다.
ex: String greeting = "Hello, " + "world!";에서 greeting 변수에는 "Hello, world!"가 저장된다.

숫자와 문자열을 함께 사용하는 경우, 숫자는 문자열로 변환되어 문자열 연결이 수행됩니다.
ex: String ageMessage = "Age: " + 25;에서 ageMessage 변수에는 "Age: 25"가 저장됩니다.

3) 여러 + 연산자가 있는 표현식에서의 연산 순서

표현식에 여러 + 연산자가 있는 경우, 연산은 표현식의 시작부터 순차적으로 수행된다.
연산의 순서는 피연산자의 타입에 따라 결과에 영향을 줄 수 있습니다. 특히, 문자열 피연산자가 하나라도 포함된 경우, 그 시점부터 나머지 연산은 문자열 연결로 처리된다.
예: String message = 1 + 2 + " apples";에서 message는 "3 apples"이 된다. 처음 두 숫자(1과 2)는 덧셈 연산이 수행된 후, 결과인 3이 문자열 " apples"와 연결됩니다.

반면, String message = "Apples: " + 1 + 2;의 경우, message는 "Apples: 12"이 된다. "Apples: " 문자열 뒤에 오는 숫자 1이 문자열로 변환되어 연결되고, 이어서 2도 문자열로 변환되어 연결된다.

0개의 댓글