JAVA/JAVA Basic

[ JAVA ] JAVA와 C언어의 차이

IT록흐 2021. 6. 18. 21:37
반응형

 

 

이것은 C언어로 작성된 한 개의 파일이다.

C는 한 개의 파일 안에 수 백, 수 천줄의 코딩을 한다. 별다른 경계점이 없다. 그냥 위에서 아래로 쭉 코딩한다. 파일을 분리하고 싶다면 자신이 원하는 부분을 분리해서 개발하면 된다. 이를 두고 '절차지향언어'라고 한다.

하지만 JAVA는 엄격하다. 자바는 개발자 마음대로 개발하면 안 된다. 자바는 클래스 단위로 개발한다.

 

클래스가 100개가 있다면 그중 99개는 라이브러리 클래스이고 1개는 실행 클래스이다. 1개의 클래스를 '실행(RUN)시키고' 그때 그때 필요한 라이브러리 클래스를 로딩시킨다.

 

C언어 로딩

C언어 파일 로딩

C는 프로그램이 RUN되기 전에 C 실행파일을 위부터 아래로 쭉 읽으며 함수를 코드 영역 메모리에 미리미리 적재한다. 이렇게 저장된 코드들은 나중에 CPU 명령어가 된다. CPU에게 명령을 내려 연산을 지시하면 CPU는 RAM에서 적절한 데이터를 갖고와 명령에 맞게 ALU 같은 연산회로를 돌린다.

전역변수, 정적변수(static), 상수들은 프로그램 시작 전에 적재되어 프로그램이 끝날 때까지 저장되어 있어야 한다. 그러므로 데이터 영역에 따로 저장시켜 놓는다.

 

 

프로그램이 실행(Run)되면 Stack 영역에 변수를 할당해야한다. 코드 영역에 이미 변수에 대한 정보가 다 들어있다. int sum = x+y; 이면 stack영역에 int형 4byte 메모리를 할당하고 그 안에 x+y의 결과값을 넣는다. 이렇게 프로그램 시작 전에 크기부터 값까지 모든 사항이 '결정'되어있는 것을 '정적 할당'이라 부른다. Stack 영역은 이미 정해진 데이터들을 저장하는 목적의 메모리 영역이다. Heap 영역은 이와 반대다.

예를 들어, 1학년 1반부터 12반까지 신입생들을 배열로 저장시킨다고 가정해보자. 반 별로 배열을 생성하려는데 문제는 반마다 학생 수가 다르다고 한다. 프로그램 사용자가 반별로 인원 수를 입력한다고 하면 프로그램은 사용자가 입력한 인원에 맞추어 배열 객체를 생성해야한다.

이렇듯, 미리 데이터의 크기가 정해져 있지 않고 사용자가 프로그램을 사용함에 따라 필요한 데이터의 크기가 달라지는 경우, Heap영역에 저장한다. 그리고 Heap영역은 포인터를 통한 접근으로 사용되어진다.

 

JAVA 로딩

 

JAVA 로딩

JAVA는 C와 달리 SDD / HDD 와 RAM 사이에 JVM이 껴있다. C언어는 위쪽 부터 아래로 쭉 코딩을 하면 컴파일러는 위부터 아래까지 쭉 읽고 실행파일을 만든다. 이를 실행하면 위부터 아래까지 쭉 한번에 RAM의 코드 영역에 적재시킨다.

이렇게 프로그램이 시작되기 전, 미리 함수들을 메모리에 할당하는 작업을 정적바인딩이라 부른다. 정적 바인딩을 하면 명령에 따라 바로 메모리에 접근이 가능하여 실행 속도가 빠르다.

하지만 자바는 다르다. 클래스 단위로 코딩을 한 후, 컴파일하여 클래스 파일(.class)을 만들고, 클래스 파일들을 한 파일로 묶어 JAR(Java Archive) 파일을 만든다. Archive란 묶음이란 뜻으로, 자바 클래스 파일들을 한 데 묶은 파일을 JAR라 부른다.

 

JDK 폴더를 들어가 보면 jrt-fs.jar 파일이 있다. 우리가 JAVA 코딩을 하는데 필요한 기본적인 클래스들을 JDK에서 미리 지원해주는 것이다. 우리가 System.out.println(); 코드를 사용할 수 있는 이유도 여기에 있다.

 

 

이클립스에 들어가 프로젝트를 생성하면 라이브러리 하나가 자동으로 생성된다. 이 라이브러리 안에는 jrt-fs.jar에 들어가 있는 클래스들이 담겨 있다.

이렇듯 JAVA는 파일이 한 가지로만 이루어져있는 것이 아니라 여러 클래스가 모여있는 '집합체'이다. 그러므로 C언어같이 전부를 메모리에 올리지 않고 프로그램을 실행하면서 필요한 클래스만을 그때 그때 참조해 메모리를 할당하는 방식을 택한다.

그래서 그 과정을 조율할 수 있는 '시스템'이 필요한데, 그것이 바로 JVM이다. 프로그램이 실행되면 JVM은 클래스가 위치한 라이브러리들과 연결된다. 연결된 라이브러리에서 JVM은 요청이 들어온 클래스를 찾고 보안검사를 한 후, 데이터를 초기화하여 메모리(메소드 영역)에 할당한다.

 

프로그램을 실행하면 static으로 선언되어, 객체생성이 필요없는 main 메소드를 실행시켜 Stack 영역에 main 스레드를 형성한다. 이제 main 메소드에 작성된 코드대로 지역변수를 할당하고 new연산자로 Heap 영역에 객체를 생성하고 그 주소를 참조변수 안에 넣는 작업을 진행한다.

여기서 객체의 메소드를 하나 호출하면, main 스레드 안에 프레임이 생성된다. 프레임은 스택에 맞게 LIFO(Last In First Out) 방식으로 생성 제거된다. 이 프레임 안에서 다시 지역변수를 할당하고, 객체를 참조하고 또 메소드를 호출하면, 그 위에 프레임 하나가 더 생성되는 원리인 것이다.


정리

C는 함수 대부분이 미리 메모리에 할당되어 있기에 속도가 굉장히 빠르다. 메모리 할당하는 과정을 프로그램 실행 중 가질 필요가 없으니 그냥 접근만 하면 된다. 하지만 이런 방식은 정해진 환경에서만 가능하다. 컴파일한 파일이 바로 컴퓨터 환경에 사용가능할 정도로 밀접하기에, OS에 따라 같은 소스 코드라 할지라도 실행파일이 전부 다르다.

하지만 JAVA는 C에 비해 속도는 느리지만 JRE(JVM)가 깔려있는 환경이라면 어떤 JAR파일도 실행이 가능하다. 뿐만 아니라 클래스 단위로 로딩되고 사용되기 때문에 클래스 별로 독립성이 확보된다. 독립적으로 사용된다는 말은 다른 프로그램에서도 재사용이 가능하다는 말과 같다. C언어는 한 가지 파일 전체가 메모리에 올라가므로 한 가지 기능만을 추출할 수 없다. 하지만 JAVA는 클래스 단위로 로딩시켜 사용하기 때문에 해당 클래스를 다른 프로그램에서 사용할 수 있다.

반응형