티스토리 뷰

 

이 콘텐츠는 아래와 같은 사전 지식이 필요합니다.

  • JAVA 프로그램의 실행 과정
  • JVM이란
  • 기본형과 참조형 자료형

사전 지식이 필요하다면, 본문의 링크 또는 더보기를 확인하십시오.


JAVA 프로그램 실행 과정

더보기

JAVA 프로그램의 실행 과정

 

 한 번에 어렵게 생각하지 말고 구체화시켜가면서 생각을 하자. 

처음 자바를 배우는 학생이라 가정하자. 소스코드를 만들고 실행 버튼을 누르면, 콘솔 창의 결과가 나온다.

조금만 자세하게 표현을 한다면, 우리가 만든 소스코드를 기계어(어셈블리어)로 변환하여, 컴퓨터가 그것을 처리하고, 화면으로 띄워준다고 할 수 있을 것이다. 구체화시키고, 시키면 끝도 없이 상세해지기 때문에 내가 생각하는 일반인의 범주에서 크게 묶어 다음과 같이 표현하였다.

 

일반인 관점의 프로그램 실행

 

   우리가 OS(Operating System)이 뭔지 모르고, Hardware가 어떻게 동작하는지 몰라도 이 흐름은 이해할 수 있을 것이다. JAVA가 실행되는 과정에서 제일 중요한 실행부 표기된 부분을 더욱 구체화시켜보겠다.

 

구체화된 실행부

 

 실행부를 큰 범주로 다시 쪼개 보면 컴파일(Compile) 환경과 런타임(Runtime) 환경으로 구분할 수 있다. 이 둘의 구분점은 프로그램이 실제로 메모리에 올라가 실행되기 전이냐 이후냐의 기준점, 즉 실행의 기준점이라 할 수 있다. 

 

컴파일 환경

컴파일은 소스코드를 자바 컴파일러를 통해 바이트코드로 변환해주는 역할을 한다. 우리가 쓰는 코드는 결국 컴퓨터에 명령을 하기 위해 쓰는 문법이다. 하지만 우리가 아무리 C, JAVA 언어를 배운다고 해서, 컴퓨터가 직접 이 언어들을 알아듣는 것은 아니다. 이 언어들은 기계어로 변환해서, 실행하고 처리한다. 그렇기에 우리가 쓴 언어를 기계어에 맞게 바꿔주는 과정을 해야 한다. JAVA compiler는 우리가 쓴 소스코드를 JAVA byte code (. class 확장자의 파일을 본 적이 있을 것이다.)로 바꾸어 JVM에 넘겨준다.

 

그러므로 엄밀히 말하면, 이것이 실행되었다고 볼 수가 없다. 당신의 컴퓨터에서 콘솔 창이 나오기 전에 빨간 줄이 그어지며, 실행을 못하게 막고 있다면, 이것은 문법적으로 byte코드로 변환할 수 없는 컴파일의 문제, 즉 컴파일 에러라는 것이다. 

 

컴파일 에러는 정리하면 다음과 같다.

 

  • 컴파일 에러는 실행 전 발생하는 에러임
  • 바이트 코드로 변화하기 위한 문법을 맞춰줘야하는데 맞추지 못해서 생긴 문법(SyntaxError)오류임
example)

 

괄호 개수가 안 맞거나, 세미콜론의 부재, 문법적 오류

classpath에 누락된 클래스(컴파일 시)

 

런타임 환경

 실제로 JVM으로 넘어가 당신의 소스코드를 실행하는 과정이다. 위의 사진에서 일반인의 관점으로는 컴파일까지 실행이라고 착각할 순 있지만, 우리는 이제 배웠으니, 명확한 실행은 런타임 환경을 지칭하는 것을 기억하자.

Byte code가 JVM으로 들어가, 해당 OS에 맞는 기계어로 컴파일되어 실행된다. 

코드를 짜다보면, 런타임 환경까지는 왔는데 (=콘솔 창까지는 실행은 되었는데), 영문 모를 빨간 에러와 함께 스스로를 화나게 하는 문장들을 종종 보게 된다. 이것이 런타임 에러다.

 

런타임 에러는 정리하면 다음과 같다.

  • 에러는  자바 바이트코드가 JVM까지는 들어왔고, 실행 중에 생긴 오류들이다.
  • 배열 인덱스를 초과하는 범위를 호출해도, 컴파일은 된다. 단, 실행 중 터질뿐이다.
  • 이처럼 컴파일상에는 문제가없어 실행이 가능하나,막상 실행해서 오류나는 경우가 이 부분에 해당한다.

여기서 의문이 들 수도 있을 것이다.

"아니, 무슨 언어를 두 번이나 컴파일해서 쓰냐, PC(정확히는 OS)에 직접 컴파일 한 번만 하면 되는 거 아냐?"

 

 충분히 그렇게 생각할 수 있다. 그러나 쓸데없이 존재하는 것은 없다. 자바의 가장 큰 특징은 JVM위에서 소스코드들이 동작한다는 점이다. 그런데 왜 JVM이라는 것을 써가면서 까지 해야 하는지 생각해보지 않았다면, 저런 의문이 충분히 든다. JVM에 대해 한번 살펴보자.  

 

 

 

JVM이란?

더보기
여러 OS들 사이에서도 JVM만 있으면, 같은 코드로 실행이 가능하다.

JVM이란

 Java Virtual Muchine의 약자다. 말 그대로 하드웨어처럼 형태는 없지만, 하드웨어와 우리의 바이트 코드를 이어주는 논리적으로 존재하는 '가상'의 머신인 것이다.

 

JVM의 구성

 

왜 쓰나요?

 C 계열 언어를 사용해 본 적이 있는가? 윈도 기반에서 쓰던 소스파일을 그대로 갖다가 리눅스에 붙여 넣으면, 안될 때가 종종 있다. OS의 환경에 따라, 코드가 적용이 될 수도 안될 수도 있는 것이다. 그렇다면, 우리가 회사를 이직하거나, 혹은 여러 OS들 사이에서도 동작하게 만들려면, 같지만 다른 언어의 차이를 숙지하고, 적용해야 한다. 이러한 스트레스를 덜어주는 것이 JVM의 큰 장점 중 하나이다. 어떤 OS환경이든, 환경에 맞는 JVM만 설치하면, 우리는 더 이상 신경 쓸 필요가 없다. JVM에게 컴파일만 잘해서 Byte code만 넘기면, 나머지는 알아서 해 줄 것이다.

이 뿐만 아니라, 데이터 적재, 객체 메모리 관리 등 여러 역할을 한다. 

 

기본형과 참조형

 

[JAVA] 자료형 - 기본형(Primitive type)과 참조형(Reference type)

목표 자료형에 대한 이해 Self-check list 기본형과 참조형을 구별할 수 있다. 자료형이란 게 뭘까? 변수를 사용하기 위해서는 변수를 담을 공간이 필요하다. 상황에 따라 큰 공간이 필요할 수도, 작

j-sik.tistory.com

 


이 콘텐츠는 아래와 같은 내용을 담고 있습니다.

  • Stack 영역과 Heap 영역

이 콘텐츠는 아래와 같은 목적을 갖고 있습니다.

  • Stack 영역과 Heap 영역을 완벽하게 학습한다.
  • 크롬 창 여러 개 켜서 공부하지 않기 위해 한번에 때려 박아 이해시킨다.

 


Java Virtual Machine 내부 구조 

 

 클래스 로더를 통해 바이트코드가 운영체제로 할당된 메모리 영역인 Runtime Data Area에 적재된다.

Runtime Data Area는 JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.

구성마다 다 큰 의미가 있지만, Runtime Data Area의 Stack과 Heap 영역에 대해 알아보자.

 

Stack 영역

 우리가 기본형 타입(Primitive Type)을 선언할 때, 해당 값들은 Stack 영역에 직접 값이 저장된다.

Stack 영역의 특징은 다음과 같다.

 

  • 후입 선출(Last In First Out) 구조를 가지고 있다.
  • 공간이 CPU에 의해 관리된다.
  • 변수 할당 해제에 신경 쓸 필요가 없다.(CPU가 관리)
  • 변수의 크기 조정 불가(기본형만 가능)
  • 변수를 사용하려면 반드시 값이 들어가야 한다. (Null X)
  • 크기가 제한적이다.

CPU가 메모리 직접 접근/관리를 하기 때문에  빠르며, 메모리 누수(Memory Leak) 문제가 없다. 

 

cf. 할당 해제가 무슨 외계 어지.?

우리가 변수를 메모리에 적재했다면, 사용하고 비워줘야 공간이 생긴다. 이렇게 변수가 공간을 사용하는 것을 할당이라고 하며, 다 쓴 변수를 메모리에서 비우는 것을 할당 해제라고 한다. 

 

 

무슨 소리인지 예를 들어 설명하겠다. 아래와 같은 코드가 있다고 하자.

 

public class Main {
    public static void main(String[] args) {
        Main test = new Main();
    }

    public Main(){
        int a = 3;
        int b = 4;
        
    }

}

 그럼 a와 b는 기본형이므로 stack영역에 적재된다. 적재된 이후에는 b가 먼저 stack 영역에서 할당이 해제되고, a가 해제된다.

 

Heap 영역

 Heap은 stack과 대조적인 특징을 보이는 영역이다. 주로 참조형(Reference Type) 변수들의 실제 값이 여기에 저장된다.

해당 영역의 특징은 다음과 같다.

 

  • 메모리 크기 제한이 없다.
  • Stack에 비해 느리다.
  • 메모리를 관리에 책임이 있다.
  • new 명령어로 생성된 인스턴스와 객체가 저장되는 영역.
  • Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.

 

public class Main {
    public static void main(String[] args) {
        Main test = new Main();
    }

    public Main(){
        int a = 3;
        int[] b = {3,4,5};
        
    }

}

 

 

참조형이 왜 '참조'형인지 명확하게 보여주는 부분이다. stack영역에서는 해당 변수의 주소 값만 가지고, heap에 있는 데이터로 접근하면, 스택을 효율적으로 사용할 수 있기 때문이다. 

 

 


포스팅에 문제가 있거나, 설명이 잘못된 부분 지적 환영합니다.

더 나은 퀄리티의 콘텐츠를 제공할 수 있도록 노력하겠습니다.

읽어주셔서 감사합니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함