Java

Java는 썬 마이크로시스템즈(현재 오라클에 합병)에서 개발한 다중 플랫폼 객체지향 프로그래밍 언어이다. Java와 JavaScript는 엄연히 다른 언어다!

설계 목표[편집 | 원본 편집]

Java 는 다음과 같은 목표를 따라 설계되고 구현되었다.[1]

  • Simple, Object-oriented and Familiar
  • Robust and Secure
  • Architecture Neutral and Portable
  • High Performance
  • Interpreted, Threaded, and Dynamic

특징[편집 | 원본 편집]

가상머신[편집 | 원본 편집]

일반적인 컴파일을 거치는 언어와 다르게, Java는 우선 컴파일러에서 바이트 코드라는 가상머신을 위한 이진 코드로 컴파일한다. 그 후 자바 프로그램이 실행될 때, 가상머신에서 인터프리터 방식으로 이를 해석하여 실행 플랫폼에 맞는 기계어로 변환한다. 이로서 다중 플랫폼을 구현하였다.

객체지향[편집 | 원본 편집]

설계 목표에 따라 Java는 객체지향으로 구현되었다. 객체의 설계를 담고 있는 클래스를 작성하고, 이를 실제로 사용할 때는 클래스에 기반한 객체를 만들어서 사용한다. C++ 와 다르게 Java의 상속은 다중 상속이 아니다. Java 의 상속은 단 하나의 부모(Parent) 클래스만을 허용한다. 대신 인터페이스를 도입하여 C++ 보다 간략하지만 다중 상속이 가지고 있는 복잡성과 문제 발생 가능성을 줄이고 보다 쓰기 쉬운 형태로 구현되었다.

가비지 컬렉션(GC)[편집 | 원본 편집]

자바는 프로그래머에게 메모리 관리를 맡기지 않는다. 프로그래머가 생성하고, 이를 직접 해제하는 게 아니라, 가상머신에서 프로그램을 잠시 멈춘후 사용하지 않는 객체를 제거한다. 이는 프로그래머의 수고를 덜어주었지만, 반대로 중간에 프로그램이 멈춰서 사용자의 불만을 초래하기도 한다.

예외 처리[편집 | 원본 편집]

Java 문법 중 클래스에 정의된 메서드가 예외(Exception)를 발생할 수 있음을 알리는 throws 키워드가 존재한다. throws 로 발생가능한 예외가 정의된 메서드를 사용할 경우, 예외 처리를 해주거나, 예외가 발생했을 경우 해당 메서드의 외부(메서드를 호출한 클래스) 쪽으로 던져주도록 처리하지 않으면 컴파일 타임에서 오류가 발생한다.

이는 컴파일 타임 수준에서 발생 가능한 오류를 점검하여 보다 안정적인 프로그램을 작성하도록 도와주는 기능이다. 개발 초기 단계에서는 보통 이를 대충 throw 만 하면서 프로토타이핑을 하지만, 완성 단계에 이르기 전까지 예외 발생 시 적절하게 처리를 하도록 try-catch를 사용해 예외처리를 구현하게 된다.

ArrayIndexOutOfBoundsException, NullPointerException 같은 실행 시 발생할 수 있는 예외(Runtime Exception)는 컴파일러가 점검하지 않는다.

장점[편집 | 원본 편집]

안정성[편집 | 원본 편집]

가상머신 위에서 돌기 때문에 자바로 만들어진 프로그램은 다른 언어로 작성된 프로그램 대비 컴퓨터와 같이 저승으로 승천하는 경우가 드물다. 하지만 다른 언어로 작성된 라이브러리를 Java Native Interface(JNI), Java Native Access(JNA) 등을 통해 끌어다 쓰는데 해당 라이브러리에서 심각한 오류가 발생하면 확실하게 맛이 가면서 뻗을 수도 있다.

다양한 라이브러리[편집 | 원본 편집]

기본적으로 다중플랫폼을 위하여 프로그램 제작에 필요한 대부분'의 클래스 및 라이브러리가 내장되어 있다. 외관은 둘째치고...

1995년에 자바가 등장하고, 전 세계적으로 널리 쓰이기 시작하면서 매우 방대한 라이브러리가 등장했으며, 인터넷을 통해 체계적으로 관리되는 Maven 중앙 저장소를 통해 약 10만종, 100만 개[2]의 다양한 라이브러리를 인터넷만 연결되면 매우 손쉽게 끌어다 쓸 수 있다. 스레드 생성, 관리하는 패키지도 자바에서 제공한다.

다중 플랫폼[편집 | 원본 편집]

인터프리터로 처리되는 자바의 특성상 다중 플랫폼을 지원한다. 현재 자바 인터프리터가 있는 OS 플랫폼은 윈도우, OS X, 우분투, 페도라 및 그 외 리눅스유닉스 계열[3], 심지어 블랙베리, 피처폰, 그 외 임베디드 플랫폼에서도 자바를 사용할 수 있다. 최근에는 Raspberry PI에서 구동할 수 있는 가상머신도 등장했다.[4]

단점[편집 | 원본 편집]

느린 속도[편집 | 원본 편집]

C같은 언어들은 기계어로 번역해서 바로 실행할 수 있는데, 바이트코드는 인터프리터를 거쳐서 실행되는 방식이기 때문에 기계어로 컴파일되어 실행되는 언어에 비해 느릴 수밖에 없다. 특히 가상머신의 초기 기동 속도 때문에 최초 실행 시 매우 느린 듯한 인상을 준다. 그러나 JIT 등의 기술을 도입해 실행속도를 향상시키려는 노력이 꾸준히 진행되었으며, 같은 로직을 수행하는 코드를 실행했을 때 필요한 시간은 C++ 대비 평균적으로 2배 정도까지 따라잡았다. 물론 일반적인 인터프리터 언어 대비 실행 속도는 당연히 훨씬 빠르다.

대량의 메모리 점유[편집 | 원본 편집]

간단한 코드를 실행하더라도 가상머신이 제대로 기동되기 때문에, 기계어 기반으로 실행되는 다른 언어 대비 메모리를 많이 소모하는 경향이 있다. 그리고 한 번 가상머신이 메모리를 점유하면, 실제로는 사용하고 있지 않아도 운영체제에 반환되지 않는다. 그래서 VMware 같은 가상 PC 프로그램 제작업체에서는 가상 머신을 위해 따로 제작된 여유 메모리 반환 프로그램과 라이브러리를 제공하는 경우도 있다.

GC 오버헤드[편집 | 원본 편집]

자바는 오브젝트가 버려질 경우, 해당 오브젝트를 바로 해제하지 않고, GC가 트리거되었을 때 해제하게 된다. 이 GC 트리거는 비결정적이며, GC 과정이 CPU-intensive 하므로, 어플리케이션은 불규칙적인 성능 저하를 가져오게 된다. 이를 극복하기 위해 지난 20년간 수 많은 노력이 있었으며, Java 8에 이르러서는 메모리와 GC에 대한 부분이 획기적으로 개선되어 호평을 듣고 있다.

  • Serial Garbage Collector: 가장 단순한 초기 형태. 단일 Thread를 사용하는 환경을 위해 설계되었으며 GC에 따른 성능 저하가 가장 크다. 즉, 멀티 코어가 기본인 요즘에는 안 쓴다.
  • Parallel Garbage Collector: 위의 것을 멀티 Thread 환경에서 동작하게 개선한 것. 좀 나아지긴 했지만 여전히 무시할 수 없을 정도로 프리징을 경험하게 된다.
  • Concurrent Mark Sweep (CMS) Garbage Collector: 참조되지 않고 사용되지 않는 객체를 마크하고 이를 필요 시 수거하여 처리하는 방식. 구현 상 위의 두 가지 방식보다 GC를 위해 CPU를 좀 더 소모하지만 코어와 Thread 개수가 많을수록 프리징을 겪을 확률이 적어진다.
  • G1 Gargbage Collector: Heap의 크기가 클 때 유리한 방식. Heap을 여러 구역으로 분할하여 병렬로 GC를 수행하는 방식.

JVM[편집 | 원본 편집]

자바 가상 머신(Java Virtual Machine)의 약자이다. 바이트 코드로 컴파일된 이진 코드를 실행하기 때문에, 꼭 자바로 작성된 코드만 실행되는 것은 아니다. 여러 플랫폼에 구현되어 있다.

JDK/JRE[편집 | 원본 편집]

JDK(Java Development Kit)는 자바 개발도구들의 집합체이고 JRE는 자바 런타임 환경의 약자로 javac로 컴파일된 바이트코드를 읽어 실행하는 것을 말한다. 과거 마인크래프트를 할 때 꼭 수동으로 설치해주어야 하는 것이었다.

각주

  1. 1.2 Design Goals of the Java™ Programming Language, Oracle, 1999, 조회일 2015-04-20
  2. 2015년 4월 기준
  3. 안드로이드는 자바를 사용하긴 하나 사정이 다른데 그 이유는 안드로이드는 달빅 바이트코드를 사용하기 때문에 자바 바이트코드를 실행할 수 없다.
  4. 애초에 자바의 목적이 가전제품에서 돌아갈 수 있도록 하는 것이었다고 한다.