Java

내위키
Dennis (토론 | 기여)님의 2020년 2월 18일 (화) 02:17 판
class Main {
  public static void main(String[] args) {
    System.out.println("You're watching NeWiki.");
  }
}

Java.

컴퓨터 프로그래밍 언어의 하나. 객체지향 프로그래밍 언어를 언급할 때 가장 먼저 손꼽히는 언어다. 선마이크로시스템즈의 제임스 고슬링이 만들었다. 이후 선마이크로시스템즈가 오라클에 인수되면서 지금은 오라클이 개발 및 관리를 하고 있다. 그러면서 온갖 소송을 일으키고 있다.[1] 원래는 컴퓨터를 넘어서 갖가지 기기를 네트워크로 연결시키고 자체 통신을 통해 동작하는 체제를 구축하기 위해서 개발한 언어인데, 지금은 서버 환경에서 가장 많이 쓰이고 있는 상황이 되었다.

철저하게 객체지향 중심으로 짜여 있다. C++가 프로그램 실행 때 시작점으로 main() 함수를 쓰는 데 반해, 자바는 public static void main(String[] args) 함수로 시작한다. 생긴 거 보면 알겠지만 클래스의 정적 메서드다. 그러면서도 C++의 객체지향 프로그램 아이디어 가운데 상당수를 살리면서도 불필요하거나 많은 오류를 일으킬 수 있는 요소들은 없애거나 단순화시켰다. C에서부터 내려오던 포인터를 없앴고, 연산자 오버로딩, 다중 클래스 상속 같은 것들도 지원하지 않는다. C++를 쓰던 사람들 눈으로 봤을 때에는 되던 게 안 되는 게 이것저것 꽤 있다 보니 어떤 면에서는 답답하기도 했다. 지금이야 C 안 배우고 바로 자바부터 배우는 사람들이 많으니 그냥 원래부터 그러려니... 다.

또 한 가지 중요한 특징은 바이트코드와 가상머신이다. 이전의 컴파일러는 최종 결과물로 바로 실행시킬 수 있는 실행 파일, 혹은 다른 오브젝트 파일이나 라이브러리 파일과 링크해서 실행 파일을 만들 수 있는 오브젝트 파일이 나왔다. 이러한 방식의 가장 큰 문제점은 결과물이 특정 운영체제나 하드웨어에 종속된다는 것이다. 예를 들어 윈도우용으로 컴파일한 실행 파일은 리눅스에서는 실행이 안 된다. 인터프리터 방식이라면 이런 문제를 극복할 수 있지만 속도가 너무 느리다.

자바가 사용한 전략은 중간 형태의 결과물을 만들어내는 것. 컴파일을 하긴 하는데, 특정 운영체제나 하드웨에어 종속되지 않은 바이트코드(bytecode)라는 중간 형태의 결과물을 만들어내고, 실행할 때에는 각 운영체제나 하드웨에어 맞춘 자바 가상머신(Java Virtual Machine, JVM)에서 이를 실행한다. 인터프리터컴파일러를 절충한 형식이라고 볼 수 있다. 컴패일러로 아예 실행파일을 만들어내는 것보다는 느리지만 인터프리터 방식보다는 확실히 빠르다. 그래도 속도가 느리다는 문제가 자꾸 지적되다 보니 결국 내놓은 해법은 JIT(Just-in-time) 컴파일러다. 예전에는 실행할 때마다 JVM이 바이트코드의 명령을 실행하는 방식이었지만, JIT 컴파일러는 처음 실행할 때 바이트코드를 기계어로 컴파일해 버리고, 그 다음에 실행할 때에는 바로 기계어로 컴파일된 것을 실행해 버린다. 이렇게 하면 프로그램의 실행 속도가 기존 컴파일러와 거의 비슷하게 빠르다. 대신 컴파일한 기계어 실행파일을 어딘가에 저장해야 하니 저장 공간은 좀 더 잡아먹고 첫 실행할 때 기계어 컴파일 과정이 필요하니 그때만 실행 속도가 느리다.

크게 세 가지 버전으로 나뉜다. 일반적인 범용 용도로 쓰기 위한 SE(Standard Edition), 대규모 엔터프라이즈 서버급의 처리가 가능한 EE(Enterprise Edition), 그리고 휴대용 기기와 같은 가벼운 장치를 위한 ME(Micro Edition) 이렇게 세 가지가 있다. 다만 모바일 기기의 성능이 발전하면서 스마트폰을 비롯한 웬만한 모바일 기기에는 ME가 아닌 SE가 들어간다. 기능을 특정한 목적으로 강하게 제한하거나 초소형화나 가격, 전원 절감을 극단적으로 하기 위해서 최대한 쥐어짠 임베디드 기기에는 ME가 들어가긴 한다.

에러 처리가 아주 잘 구조화되어 있는 것 같지만 실제로는 장난 아니게 비효율적이다. C++의 try-catch 방식을 가져다 쓰고 있는데, 결국 일어날 만한 에러의 유형마다 에러 핸들러를 만들어 줘야 하고 제대로 하려면 여기에 들어가는 코드 양만 해도 장난이 아니다. 또한 함수를 정의할 때 어떤 예외를 던질 것인지를 선언해야 하며 만약 함수 내부에서 일어날 수 있는 예외를 함수 정의부에서 선언해 주지 않으면 컴파일 에러를 일으킨다. 만약에 A 함수 내부에서 사용하는 B 함수가 던지는 예외를 A 함수 정의 부분에서 선언해 주지 않으면 이 역시 컴파일 에러를 일으키므로 문제가 더더욱 복잡해진다. 그러다 보니 코드를 짤 때 이러한 선언을 필요로 하지 않는 RuntimeException을 남발하는 문제를 낳게 되었다. 너무 엄격한 규칙이 오히려 대충 대충 프로그래밍의 원인이 되어 버린 것이다. 앞선 예의 경우에도 B 함수를 try-catch로 둘러싼 다음에 예외를 씹어버리거나 RuntimeException을 던져버리거나... Go는 이 기능을 버렸고 자바 가상머신과 호환되는 언어인 코틀린은 이러한 제약을 많이 완화시켰다.

각주

  1. 이 자바 관련 문제가 오라클오픈소스 커뮤니티의 공공의 적으로 찍힌 결정적인 이유 가운데 하나다. 그밖에도 오픈오피스.org, MySQL오픈소스 커뮤니티가 오라클을 싫어하게 만든 원인을 제공했다.