[JAVA]의 역사 JVM

최웅진·2023년 5월 28일
0

Java

Java의 역사는 1991년 6월 Sun Microsystems에 다니던 제임스 고슬링 이 만들었습니다.

왜 새로운 언어를 만들었을까?

자바는 초기에 토스터, 전자레인지, 리모콘 등의 가전제품에 사용되는 임베디드 소프트웨어 를 위해 만들어졌습니다.
이미 C, C++ 등 하드웨어에서 쓰이는 언어가 있었는데 왜 새롭게 언어 까지 만들었을까요?

당시 대부분의 컴퓨터 언어는 특정 플랫폼(또는 OS)이나 하드웨어에 맞게 컴파일 되도록 설계되었는데 플랫폼마다 그리고 각 플랫폼에서 쓰이는 CPU 마다 해당 환경에 맞는 컴파일러가 필요했기 때문에 개발 비용이 비싸고 오래 걸렸다고 합니다.

예를 들어 C++ 프로그램의 경우 모든 종류의 CPU에 맞게 컴파일될 수 있지만 플랫폼과 CPU에 따라 다른 C++ 컴파일러가 필요했습니다.

따라서 제임스 고슬링과 동료들은 OS에 상관없이, CPU에 상관없이 다양한 환경에서 실행 되는, 이식성이 뛰어난 Cross Platform 언어의 개발에 착수했고, 이러한 배경을 바탕으로 Write Once, Run Anywher(WORA)의 철학을 가진 자바의 탄생으로 이어졌습니다.


왜 이름이 Java 인가요?

초기에는 언어이름이 자바가 아니라 오크(Oak)였습니다. 당시 썬 마이크로시스템즈 Green Team 에 소속된 제임스는 처음에는 본인의 팀명을 따서 이름을 그린톡(Greentalk)으로 지었다가, 사무실 바깥의 오크나무를 보고 오크(Oak)로 바꾸었습니다.

하지만 후에 Oak라는 이름이 Oak Technologies에서 이미 사용 중이라는 사실을 알고, 동료들과의 회의를 거쳐서 "dynamic", "revolutionary", "Silk", "jolt", "DNA” 등의 이름 후보 중 최종적으로 인도네시아 자바섬에서 재배되는 커피원두에서 차용된 자바(Java) 라는 이름으로 결정되었습니다. (그래서 자바 로고에 커피가 있다는...)

결론적으로 1991년에 오크(Oak)라는 이름으로 시작하여, 1996년에 발표된 1.0.2 버전부터 자바(Java)라는 이름을 사용하게 되었습니다.


자바의 특징

자바의 개발자들은 유닉스(Unix) 기반의 배경을 가지고 있었기 때문에 문법적인 특성은 파스칼이 아닌 C++의 조상인 C언어와 비슷합니다.
그리고 C 에 객체 지향적 기능을 추가하여 만든 C++과는 달리, 처음부터 객체 지향 언어로 개발된 프로그래밍 언어 입니다.

위에서 자바를 만든 이유에서 설명했듯 자바의 가장 큰 특징은 컴파일된 코드가 플랫폼(또는 OS), CPU에 독립적이라는 점 입니다.

자바 언어는 다섯 가지의 특징이 있으며, 다음과 같습니다.

It should be "simple, object-oriented and familiar"
It should be "robust and secure"
It should be "architecture-neutral and poratble"
It should execute with "high performance"
It should be "interpreted, threaded, and dynamic"

이를 번역해보면 다음과 같다.

1. 자바는 "단순하고, 객체지향이며, 친숙"해야 한다.

2. 자바는 "견고하며, 보안상 안전"하다.

3. 자바는 "아키텍처에 중립적이어야 하며 포터블"해야 한다.

4. 자바는 "높은 성능"을 제공해야 한다.

5. 자바는 "인터프리터 언어이며, 쓰레드를 제공하고, 동적인 언어"이다.

1) 자바는 "단순하고, 객체지향이며, 친숙"해야 한다.
자바는 처음 만들 때부터 객체지향으로 디자인되어 있다. 그리고, 다형성, 캡슐화 등 객체 지향 언어의 특징들을 지원할 수 있는 구조로 되어 있다.
그리고, 자바로 개발할 때에는 처음부터 모든 것을 만들 필요가 없다. 개발하면서 필요한 여러 기능들은 이미 API를 통해서 제공하고 있다. 파일을 읽고 쓰거나 네트워크로 데이터를 주고 받는 I/O, 그래프 UI 등을 개발하기 위한 여러 라이브러리를 통해서 보다 쉽게 개발할 수 있는 환경을 제공하고 있다. 파일을 읽고 쓰거나 네트워크로 데이터를 주고 받는 I/O, 그래픽 UI 등을 개발하기 위한 여러 라이브러리를 통해서 보다 쉽게 개발할 수 있는 환경을 제공한다.

2) 자바는 "견고하며, 보안상 안전"하다.
자바는 컴파일할 때와 실행할 때 문법적 오류에 대한 체크를 한다. 메모리 관리 모델이 매우 단순하고, C를 배우고 사용하는 개발자들의 머리를 아프게 하는 포인터의 개념이 없다. 이 특징들은 자바를 매우 믿을 수 있고(reliable) 견고한 소프트웨어가 될 수 있도록 도와준다.

자바는 기본적으로 분산 환경에서 사용하기 위하여 디자인되었다. 분산 환경에서 보안은 중요한 부분 중 하나다. 자바 기술은 외부에서 침입이 불가능한 애플리케이션을 만들 수 있도록 해준다.

3) 자바는 "아키텍처에 중립적이어야하며 포터블"해야 한다.
자바로 작성한 프로그램은 매우 다양한 하드웨어 아키텍처에서 수행할 수 있도록 되어 있다. 따라서 자바는 아키텍처에 중립적인 바이트 코드를 제공한다. 따라서, 자바의 버전만 동일하다면, 동일한 프로그램은 어떤 플랫폼에서도 실행할 수 있다. 이러한 호환성과 포터블한 환경을 제공하는 것은 JVM 덕분이다.

4) 자바는 "높은 성능"을 제공해야 한다.
자바는 실행 환경에서 최대한의 성능을 낼 수 있도록 되어 있다. 게다가 자동화된 가비지 컬렉터는 낮은 우선 순위의 쓰레드로 동작하기 때문에 보다 높은 성능을 낼 수 있다. 그리고, 보다 빠른 성능을 위해서 네이티브 언어로 작성한 부분을 자바에서 사용할 수 있도록 되어 있다.

5) 자바는 "인터프리터 언어이며, 쓰레드를 제공하고, 동적인 언어"이다.
자바 인터프리터는 자바 바이트 코드를 어떤 장비에서도 수행할 수 있게 해준다. 따라서, 시존에 사용하던 무거운 컴파일과 링크와 테스트 사이클을 거쳐야 하는 개발 환경보다 빠른 환경을 구축할 수 있다.(하지만 지금의 자바 개발 환경은 각종 라이브러리들로 인해 그렇게 단순하지만은 않다.)

자바는 멀티 쓰레드 환경을 제공하기 때문에, 동시에 여러 작업을 수행할 수 있다. 따라서 사용자에게 매우 빠른 사용 환경을 제공한다.

자바 컴파일러는 컴파일시 매우 엄격한 정적인 점검을 수행한다. 그리고, 실행시에 동적으로 필요한 프로그램들을 링크시킨다. 게다가 새로운 코드는 다양한 소스에서 요청에 의해서 연결될 수 있다.


JDK, JRE

  • JDK : Java Development Kit
  • JRE : Java Runtime Environment

가장 좌측을 보면 JDK와 JRE로 나뉘어져 있는 것을 볼 수 있다.
즉, JRE는 자바를 실행하기위한 환경의 집합이라고 보면된다.
그리고, JRE에 있는 여러 가지 레고 블럭처럼 칸칸이 쌓여 있는 것들은
자바에서 제공하는 라이브러리들 이라고 보면 된다.


JVM과 GC

일반적으로 자바를 실행할 때 많이 사용되는 용어들은 다음과 같은 것들이 있다.

  • JVM : Java Virtual Machine(자바 가상 머신)
  • GC : Garbage Collector(가비지 컬렉터)

먼저 JVM에 대해서 간단히 알아보자. JVM은 작성한 자바 프로그램이 수행되는 프로세스를 의미한다. 다시 말해서, Java라는 명령어를 통해서 애플리케이션이 수행되면, JVM 위에서 애플리케이션이 동작한다. 이 JVM에서 작성한 프로그램을 찾고 수행하는 일련의 작업이 진행된다.

자바의 메모리 관리는 개발자가 하지 않아도 된다. 메모리 관리를 JVM이 알아서 하기 때문이다. 이때 JVM 내에서 메모리 관리를 해주는 것을 바로 "가비지 컬렉터"라고 부른다. Garbage는 우리나라말로 "쓰레기"라는 의미이며, 사용하고 남아 있는 전혀 필요 없는 객체들이 여기에 속한다. 아무리 가비지 컬렉터가 쓰레기를 알아서 청소한다고 하더라도, 메모리를 효율적으로 사용하도록 개발하는 것은 매우 중요하다. 예를 들어, 쓰레기를 청소하는 작업이 수행되면 "가비지 컬렉션이 수행되었다"라고 표현한다. 아니면 짧게 "GC가 발생했다"라고 이야기 한다.

어떤 객체를 생성하더라도 그 객체는 언젠가는 쓰레기가 되어 메모리에서 지워져야만 한다.
예를 들어 "abc"라는 문자열이 있는데, 더 이상 사용할 일이 없다면 메모리에서 삭제 되어야만 한다.
만약 지워지지 않으면, 자바 프로그램은 엄청난 메모리가 필요할 것이다. 그래서 C를 사용하여 개발할 때에는 메모리를 해제하는 작업을 꼭 해줘야만 한다.
하지만, 자바는 그런 작업을 해 줄 필요가 없다.
가비지 컬렉터라는 것이 알아서 쓰레기들을 치워주기 때문이다.

Java7부터 공식적으로 사용할 수 있는 G1(Garbage First)라는 가비지 컬렉터를 제외한 나머지 JVM은 다음과 같이 영역을 나누어 힙(Heap)이라는 공간에 객체들을 관리한다.

가장 왼쪽에 있는 Young 영역에는 말 그대로 젊은 객체들이 존재하며, Old 영역에는 늙은 객체들이 자리잡게 된다. 그리고, Perm이라는 영역에는 클래스나 메소드에 대한 정보가 쌓인다.

Young 영역에는 Eden과 두 개의 Survivor 영역으로 나뉘는데, 이 중에서 객체를 생성하자마자 저장되는 장소는 Eden이다. 일반적으로 자바에서 메모리가 살아가는 과정은 다음과 같다.

  1. Eden 영역에서 객체가 생성된다.
  2. Eden 영역이 꽉 차면 살아있는 객체만 Survivor 영역으로 복사되고, 다시 Eden 영역을 채우게 된다.
  3. Survivor 영역이 꽉 차게 되면 다른 Survivor 영역으로 객체가 복사된다. 이 때, Eden 영역에 있는 객체들 중 살아있는 객체들도 다른 Survivor 영역으로 간다. 즉, Survivor 영역의 둘 중 하나는 반드시 비어 있어야만 한다.

지금까지 과정을 마이너(minor) GC 혹은 영(Young) GC라고 부른다. 여기서 GC는 가비지 컬렉터가 아니라 가비지 컬렉션을 말한다.

그러다가, 오래 살아있는 객체들은 Old 영역으로 이동한다. 지속적으로 이동하다가 Old 영역이 꽉 차면 GC가 발생하는데 이것을 메이저(major) GC, 풀(Full) GC라고 부른다.

그렇다면 영 GC와 풀 GC 중 어떤 것이 더 빠를까?

영 GC가 풀 GC보다 빠르다. 왜냐하면 일반적으로 더 작은 공간이 할당되고, 객체들을 처리하는 방식도 다르기 때문이다. 그렇다고, 전체의 힙 영역을 영 영역으로 만들면 장애로 이어질 확률이 매우 높아진다.

오라클 JDK에서 제공하는 GC의 방식은 크게 4가지가 있으며, Java7부터 추가된 G1(Garbage First)를 포함하여 총 5가지의 가비지 컬렉터가 존재한다. 정리하자면 다음과 같다.

  • Serial GC
  • Parallel Young Generation Collector
  • Parallel Old Generation Collector
  • Concurrent Mark & Sweep Collector(줄여서 CMS)
  • G1(Garbage First)

이중에서 WAS로 사용하는 JVM에서 사용하면 안되는 것은 Serial GC다. 이 GC 방식은 -client 옵션을 지정했을 때 사용된다. 즉, 클라이언트용 장비에 최적화된 GC이기 때문에 만약 WAS에서 이 방식을 사용하면 GC 속도가 매우 느려 웹 애플리케이션이 엄청 느려진다.

참고

  • 자바의 신
profile
PlayData

0개의 댓글