기본타입과 참조타입

김재영·2022년 11월 11일
0

항해99 Pre_Onboarding

목록 보기
4/5

5일차

챕터5 - 참조타입

기본타입과 참조타입

자바의 타입은 기본 타입(primitive type)과 참조 타입(reference type)으로 나뉜다

기본타입

  • 정수, 실수, 문자, 논리 리터럴을 저장하는 타입

참조타입

  • 객체(object)의 번지를 참조하는 타입
  • 배열, 열거, 클래스, 인터페이스

기본 타입 변수 - 변수와 값이 stack영역에 직접 저장
참조 타입 변수 - 값은 주소를 할당받아 heap영역에 저장되고 stack영역에는 변수와 값을 참조할 수 있는 주소가 저장

JVM

JVM(Java Virtual Machine)이란

Java를 실행하기 위한 가상의 기계로 JVM은 Java를 OS에 종속받지 않고 실행하기 위해서 사용한다
JVM을 사용함으로써 CPU가 Java를 인식하고 실행할 수 있게된다

이전 C/C++은 컴파일된 플랫폼과 실행될 타겟 플랫폼이 다를 경우 프로그램이 동작하지 않았다
OS마다 지원하는 System Call interface가 다르고
CPU마다 지원하는 Instruction Set Architecture이 달라
바이트코드의 변환 방법이 달라 코드가 동작하지 않기 때문이다

C/C++는 이 문제를 크로스 컴파일(Cross Compile)로 해결했다
크로스 컴파일이란 타겟이 될 플랫폼에 맞춰 컴파일 하는것이다
크로스 컴파일을 함으로써 C/C++도 여러 플랫폼에서 동작할 수 있게 되었다

하지만 Java의 bytecode는 타겟 플랫폼과 관계없이 JVM 위에서 동작하게 된다
사용자는 플랫폼에 맞는 전용 JVM을 설치하기만 하면 된다

JVM의 동작


Java의 소스코드(?.java)는 CPU가 인식할 수 있도록 기계어로 compile 해야한다
Java는 JVM을 거쳐서 Java bytecode(?.class)로 하게된다
(.class 파일은 Java bytecode를 담고있는 파일이다)

Java compiler가 .java를 .class라는 Java bytecode로 변환한다

하지만 변환된 Java bytecode는 기계어가 아니기 때문에 바로 실행되지않고
JVM이 OS가 Java bytecode를 이해할 수 있도록 해석해주면서 실행되게 된다

JVM의 내부 구조


class loader

  • JVM내부로 .class 파일을 로드하고 링크를 통해 배치한다
  • 런타임시 동적으로 class파일을 로드한다

runtime date area

  • JVM이 Java bytecode를 실행할 때 사용하는 메모리 영역

  • method area

    • JVM이 시작할 때 생성된다
    • class loader가 class 파일을 읽어오면 class data를 parsing해서 method area에 저장한다
    • 클래스 별로 정적 필드(static field)와 상수(constant), 메소드코드, 생성자코드, 변수, 바이트 코드 등이 저장된다
    • 모든 스레드가 공유하는 영역이다
  • heap

    • 프로그램을 실행하면서 생성한 모든 object를 heap에 저장한다
    • 모든 스레드가 공유하는 영역이다
  • Java stack

    • 스레드에서 메소드가 호출될때 stack frame을 추가(push)한다
    • 최상위 stack frame은 main method를 담고있다
    • java stack은 모든 스레드를 통들어 1개만 존재한다
    • 메소드 실행이 끝나면 해당 프레임을 제거(pop)한다
      • stack frame
        • 스택 프레임은 Local variables array, Operand stack, Frame data를 포함한다
        • Operand stack는 연산될 데이터를 저장한다
        • Frame data는 Constant Pool,이전 stack frame에 대한 정보, 현재 메소드가 속한 Class와 Object에 대한 참조 등의 정보를 담는다
  • PC registers

    • PC(Program Counter) register
    • 각 스레드는 메소드를 실행하고 있다 그 때 그 메소드 안에서 다음 Fetch될 bytecode의 주소를 담고있다
  • native method stacks

    • Java bytecode가 아닌 다른 언어를 컴파일해서 사용하기 위한 메소드

execution engine

  • bytecode를 JVM내부에서 두가지 방식으로 실행할 수 있는 형태로 변환한다
  • Interpreter
    • bytecode를 명령어 단위로 한줄씩 읽어 실행한다
  • JIT(Just-In-Time)
    • 인터프리터 방식을 보완하여 실행 중에 컴파일을 진행한다(동적 컴파일)
    • 기계어로 변환된 코드를 캐시에 저장시켜 재사용시 컴파일을 진행하지 않는다
    • 캐시된 코드를 사용하면 미리 컴파일된 코드를 사용하는 효과(정적 컴파일)를 낸다
    • JVM의 캐시공간은 매우 작기 때문에 내부적으로 해당 메소드가 얼마나 자주 수행되는지 체크하고 기준에 따라 다시 컴파일을 수행한다

JVM의 GC

GC(Garbage Collector)은 Mark와 Sweep과정으로 수행된다

  • GC가 stack의 모든 변수를 읽으면서 어떤 Object를 참조하고 있는지 Mark한다
  • Reachabel Object가 참조하고 있는 Object도 찾아서 Mark한다
  • 마킹되지 않은 Object를 heap영역에서 sweep한다
    단점
    • GC가 동적하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생한다
    • GC가 너무 자주 동작하면 SW의 성능 하락의 문제가 된다
    • 개발자가 메모리가 언제 해제되는지 정확하게 알 수 없다

String 타입

String과 new String()의 차이

public class Self_04_1_5 {
    public static void main(String[] args) {
        String name1 = "홍길동";
        String name2 = "홍길동";
        String name3 = new String("홍길동");
        String name4 = new String("홍길동");
        String name5 = new String("홍길동").intern();

        System.out.println(name1 == name2);
        System.out.println(name3 == name4);
        System.out.println(name1 == name5);
        }
    }
> Task :Self_04_1_5.main()
true
false
true

String name1 = "홍길동" 의 경우

  • stack영역에는 name1이라는 String타입 변수와 "홍길동" 이라는 값의 주소가 저장된다
  • heap영역에는 할당 받은 주소에 "홍길동" 이라는 값이 저장된다
    정확히는 heap영역 내부에 있는 String pool로 저장되게 된다
  • name1과 name2를 비교하면 String pool에는 홍길동 이라는 문자열이 단 1개 존재하게 되며 두 변수는 이를 참조하게 되며 true가 나오게 된다

String name3 = new String("홍길동") 의 경우

  • new 생성자는 String pool내부가 아닌 heap영역에 Object를 생성하게 된다
  • name3과 name4는 서로 다른 주소를 가진 채 heap영역에 생성된다
  • 즉 heap영역에 주소가 다른 홍길동 객체가 2개 생기게 된다
  • 그로인해 name3과 name4를 비교하면 다른 주소를 참조하니 false가 나오게 된다

new String으로 생성한 Object를 String pool에 저장하기 위해서 intern()을 사용한다
그러면 heap영역내부 String pool외부에 있던 name5의 홍길동이 String pool내부로 들어가
name1과 name5를 비교하면 같은 주소를 참조하여 true가 나오게 된다

profile
Kickoff 22-10-19

0개의 댓글