JDK 1.1 Tutorial

김도형

대전 광역시 유성구 구성동

한국과학기술원 전산학과

E-mail :dynaxis@pllab.kaist.ac.kr

URL : http://pllab.kaist.ac.kr/~dynaxis/

Abstract:

1995년 5월 공식적으로 발표된 뒤 자바 기술은 그 혁명적인 개념으로 인해 컴퓨터 산업 전반에 있어서 근간의 어느 기술보다도 큰 영향을 끼치고 있다. 웹 상의 실행 가능한 내용(executable contents)로서 세상에 등장한 이후 자바는 역사상 어느 플랫폼보다 빠르게 발전하여 왔다. 이제는 네트웍 시대를 가는 컴퓨터 업계의 열린 표준으로서 다양한 분야로의 적용이 이루어지고 있으며, 그에 맞게 자바 가상기계, API(Application Programming Interface)의 개선과 발전이 병행되고 있다.

여기서는 먼저 자바 기술의 전반에 살펴보기로 하겠다. 그리고, 그 특성과 활용 범위, 성능 문제에 대해 살펴보면서 2년이 지난 지금 자바의 가능성에 대한 새로운 평가를 내려볼 것이다. 아울러 자바의 적용범위를 기업 전반으로 확장시키려는 시도의 신호탄인 JDK 1.1에 대해 알아보도록 하겠다.

Keywords:

자바, 자바 언어, 자바 가상기계, 자바 API, JDK 1.1

1. 자바란 무엇인가?

1.1 자바 플랫폼 (Java Platform)

는 일반적인 인식과는 달리 프로그래밍 언어, 가상기계, 그리고, API를 포괄하는 소프트웨어 플랫폼(software platform)으로 이해되어야 한다. 우리가 익숙한 PC의 윈도즈 환경과 비교해보자. 자바 언어는 일반적으로 사용되는 언어인 C/C++에 해당되고, 자바 가상기계는 80x86계열의 CPU, 자바 API는 Win32 API와 MFC(Microsoft Foundation Classes)에 해당한다고 생각할 수 있다. 보통 자바 실행 환경은 유닉스, 윈도즈와 같은 다른 OS(Operating System)하에서 소프트웨어적으로 구현된다. 물론 예외도 있지만 그에 대해서는 뒤에 와 에 대해 설명하면서 자세히 다루기로 하자. 다음 은 특정 시스템하에서 자바 실행 환경과 그 시스템의 OS 및 그 위에서 실행되는 응용프로그램이 공존하는 상황을 서로 비교하기 쉽게 구성한 것이다. 그림에서 위 쪽은 자바의 경우를 나타낸 것이고 아래 쪽은 윈도즈 환경과 같은 일반적인 소프트웨어 환경을 나타낸 것이다.

자바

자바 운영체제

자바칩

그림

C언어가 기계어로 컴파일되듯 자바 언어는 자바 가상기계의 "기계어"에 해당하는 "바이트코드(bytecode)"로 컴파일된다. 컴파일된 바이트코드는 자바 가상기계에 의해 해석되어 실행되게 되는데, 자바 가상기계는 그림에서 보는 바와 같이 보통은 해석기(interpreter)나 프로그램 수행 도중 기계어를 생성하는 JIT(Just-In-Time) 컴파일러 등 소프트웨어적인 방법으로 구현된다. 하지만, 이와 달리 최근에는 C/C++ 와 같이 자바 원시코드에서 특정 CPU의 기계어를 직접 생성하는 컴파일러도 나와 있으며, 자바칩(JavaChip)과 같이 하드웨어적으로 바이트코드를 직접 수행하는 CPU도 개발되고 있다. 이에 대해서는 뒤에 자바 가상기계에 대한 상세한 설명에서 함께 다루도록 하겠다.

한편 이렇게 실행되어지는 자바 응용프로그램들은 화면에 그림을 표시하거나 파일을 읽고 쓰는 등의 입출력 작업을 하기 위해 자바의 API들을 호출해야 한다. 유닉스 상의 응용프로그램들이 시스템 호출(system call)을 사용하거나, 윈도즈 응용프로그램들이 Win32 API를 사용해서 OS(Operating System)에게 서비스를 요청하는 것과 마찬가지라고 할 수 있다. 뒤에 자세히 설명하겠지만 바이트코드에는 입출력 명령이 없으므로 바이트코드만으로 이루어진 프로그램은 결코 입출력을 할 수가 없다. 즉, C/C++나 어셈블리어로 작성되어 기계어로 번역된 프로그램의 도움을 받아야 한다. C/C++, 어셈블리 등의 언어로 작성되어 자바가 수행되는 특정 CPU의 기계어로 컴파일된 프로그램들을 자바 바이트코드와 구분해서 "고유 코드(native code)"라고 부른다. 자바에서는 특정 객체의 메쏘드(method)들을 고유 코드로 작성할 수 있으며 순수하게 자바로 작성된 프로그램은 메쏘드 호출의 형태로 고유 코드로 작성된 메쏘드들을 실행할 수 있다. 바로 이런 이유로 자바 플랫폼의 핵심적인 요소중 하나로 자바 API가 포함되어야 하는 것이다.

1.2 JDK와 JRE

JDK(Java Development Kit)는 자바 프로그램을 개발하고 실행할 수 있는 도구의 집합이다. 현재 썬의 자회사인 에서 무료로 배포하고 있는 JDK에는 자바 가상기계가 "java"라는 이름의 해석기(interpreter) 프로그램으로 구현되어 있으며, 그 외에 자바 원시코드를 바이트코드로 컴파일해 주는 컴파일러인 "javac"와 디버거인 "jdb" 등의 개발 도구가 함께 포함되어 있다. 보통 의 "비쥬얼 J++(Visual J++)", 의 "카페"와 같은 자바 개발도구나 , 마이크로소프트의 웹 브라우저에 포함되는 자바 가상기계와 라이브러리들은 JDK에 포함된 것을 기본으로 개선을 위해 일부 수정된 것들이다.

자바소프트(Javasoft)

마이크로소프트

시맨텍

넷스케이프

최근 JDK 1.1이 나오면서 자바소프트에서는 JDK외에 JRE(Java Runtime Environment)라는 별도의 패키지를 배포하기 시작했다. 이는 JDK에서 자바 프로그램을 수행하기 위해 필수적인 부분만을 모은 것으로 자바로 프로그램을 작성한 사람이 자신의 프로그램과 함께 로얄티 없이 배포할 수 있도록 제공되는 것이다. 프로그램을 작성하기 위한 "javac", "jdb"와 같은 도구들은 제외되어 있고 자바 가상기계와 라이브러리 측면에서는 JDK와 동일하다. 마이크로소프트에서도 이와 유사하게 자사의 자바 SDK(Software Development Kit)의 일부를 JRE와 유사한 조건으로 배포할 수 있도록 하고 있다.

1.3 애플릿(applet)과 어플리케이션(application)

애플릿은 HTML 페이지에 포함되어 자바 가상기계 및 라이브러리를 탑재한 웹 브라우저 상에서 실행되는 자바 프로그램을 말한다. 네트워크를 통해서 원거리에 있는 서버로부터 애플릿을 구성하는 자바 바이트코드를 전달받아 수행하는 구조이며, 초창기 대부분의 자바 프로그램들이 이 부류에 속한다. 이에 비해 어플리케이션은 흔히 사용하는 워드프로세서 등의 프로그램과 같이 독립적으로 수행되는 자바 프로그램을 지칭하는 용어로 보통 JDK, JRE에 포함된 자바 실행환경을 사용하여 실행시킨다.

애플릿은 일반적으로 네트워크를 통해 전송되므로 전송속도를 감안해서 크기가 작은 것이 보통이며, 인터넷상의 불특정 서버로부터 애플릿을 전송받아 실행하는 경우가 많으므로 어플리케이션에 비해 보안에 관련된 제약이 많은 편이다. 현재 넷스케이프를 포함한 대다수의 웹 브라우저에서는 현재 JDK 1.0.2와 동일한 규격의 자바 실행환경을 탑재하고 있는데 이들 브라우저 상에서는 애플릿에 대해 다음과 같은 제약을 가하고 있다.

애플릿이 실행되는 시스템의 파일에 접근할 수 없다.

애플릿을 가져온 호스트(host)로만 네트워크 연결을 열 수 있다(URL 클래스를 사용하든지 Socket 클래스를 사용하든지 마찬가지)

C/C++로 쓰여진 고유 코드 라이브러리를 사용할 수 없다.

구체적인 내용은 을 참고하기 바란다. 이런 이유로 애플릿이 데이터를 저장하고자 할 때는 애플릿을 제공하고 있는 서버측에 네트워크 연결을 해서 서버측의 파일에 정보를 저장해야 한다. CGI를 쓰거나 별도의 서버를 작성하는 방법이 있는데, 이에 대한 자세한 설명과 예제는 를 참고하기 바란다. 뒤에 언급할 JDK 1.1에서는 전자서명을 이용하여 특정 애플릿에게 추가적인 권한을 줄 수 있게 하고 있으며, 최근 발표에 따르면 앞으로 넷스케이프나 인터넷 익스플로러와 같은 웹 브라우저에서도 사용자 확인하에 애플릿이 파일 입출력 등의 추가적인 권한을 가질 수 있도록 할 것이라고 한다 .

[참고 1]

[참고 2]

[참고 3]

일반적으로 애플릿과 어플리케이션을 구분하지만, 위에 언급한 제약을 제외하면 실행되는 방법의 차이가 있을 뿐 근본적으로 애플릿과 어플리케이션은 그 능력에 있어서 차이가 없다. 애플릿이 웹 페이지 상에 그림과 같이 영역을 차지하기는 하지만 어플리케이션과 마찬가지로 별도로 윈도를 띄울 수 있으며, 전자서명 등의 방법으로 허가를 얻으면 파일 입출력이나 네트워크 연결도 자유로이 행할 수 있다. 앞으로 네트워크 컴퓨터가 일반화되면 대부분의 응용프로그램들은 웹 페이지 상에서 애플릿의 형태로 제공될 것이다. 이런 인트라넷(intranet) 환경에서는 전송 시간이 큰 문제가 되지 않을 것으므로 애플릿으로 제공되는 프로그램의 크기 또한 문제가 되지 않을 것이다.

자바는 네트워크를 위한 언어라고 일컫어진다. 이는 API상의 네트워크 지원과 함께, 애플릿과 같이 네트워크를 통해 실행파일이 옮겨다니는데 있어서 여러가지로 좋은 특성을 가지고 있음에 기인한다. 마이크로소프트의 와 같은 기술과 비교할 때, 전송시의 효율, 안전성, 그리고, 실행시의 보안 문제 등에 있어서 월등히 뛰어나다. 이에 대해서는 뒤에 자세히 언급하도록 하겠다.

액티브 X

2. 자바 기술의 특성

2.1 자바 프로그래밍 언어 (Java Programming Language)

자바 프로그래밍 언어는 C/C++의 문법을 기본으로 Eiffel, SmallTalk, Objective C, Cedar/Mesa 등의 언어를 참고하여 개발되었다. 초기의 C 언어가 그랬듯이 자바는 객체지향 언어이면서도 언어자체는 무척 간단하다. 다음은 C/C++를 염두에 두고 자바 언어의 특징을 정리해 본 것이다.

□ C/C++을 닮았다: C/C++가 옮겨가기에 용이하다.

□ 객체지향(Object Oriented) 언어이다: C++에 비해 순수 객체지향에 가깝다.

□ 이식성이 좋다: 언어 자체가 엄격하게 정의되었다.

□ 모든 기본 자료형의 표현 형식과 범위가 명확히 명시되어 있다.

e.g. int : 32bit 2의 보수 표기

e.g. i == 0 일 때, ++i + --i 는?

자바 - 항상 1 ('+'의 왼쪽부터 값을 계산)

□ C/C++ - 컴파일러에 따라 값이 틀려질 수 있다. (언어 정의시 계산 순서에 대한 명시가 되어있지 않다)

□ 간단하다

□ 다중상속(multiple inheritance), 연산자 중복 정의(operator overloading) 등 C++에서 부작용이 많았던 부분을 과감히 삭제

□ 포인터가 없다: char (*(*x[3])())[5]와 같은 복잡한 형 선언이 있을 수 없다.

□ Strongly Typed

□ C++보다 엄격

□ 형 검사를 통해 컴파일시에 보다 많은 오류를 검출

□ 포인터가 없다: C 스타일의 포인터 연산이 없다. 단지, 참조형(reference type)이 존재

□ 범위를 검사하는 배열이 제공된다.

□ 가베지 콜렉션 (garbage collection) 사용

□ 메모리를 할당 받은 후 free할 필요가 없다.

□ 경우에 따라 malloc-free보다 높은 성능

□ 언어차원에서 다중 쓰레드(multithread)간의 동기화를 지원

□ 모니터(monitor)에 의한 고수준 동기화 지원

□ 자바의 모든 클래스 라이브러리는 이미 멀티쓰레드에 대해 안전하다. (thread-safe)

□ 예외처리(exception handling) 지원

□ try catch finally : C++와 유사

□ 자바의 모든 클래스가 이미 예외처리를 사용

□ 예외를 처리하는 코드를 프로그램의 주된 흐름과 분리 - 읽기 쉽고 관리하기 쉽다.

□ 동적이다.

□ 실행시 데이터 형 구분

□ 동적 링크 - 수정된 모듈만 컴파일

□ 패키지(package) 단위의 클래스 관리

□ 클래스의 꾸러미

□ 헤더파일(header file)이 필요없음: 컴파일된 프로그램 자체가 헤더 파일에 해당하는 정보를 가지고 있다.

□ 큰 프로그램 작성시 이름 충돌 제거

□ 유니코드 사용

□ 자바 1.0 : 유니코드 1.0

□ 자바 1.1 : 유니코드 2.0

□ char 형이 16bit

□ 여러 언어를 동시에 사용하는 프로그램 작성 가능

특히 위에서 포인터가 없고, 배열에서 범위 검사를 행하며, 가베지 콜렉션을 행하는다는 특성은 일반적으로 C/C++로 프로그래밍하는 경우 부딪히는 대부분의 오류인 메모리 오류를 대폭 제거할 수 있다는 점에서 매우 중요하다. 가베지 콜렉션은 가장 낮은 순위로 실행되고 있는 별도의 쓰레드에 의해 행해지므로 보통 사용자 입력을 기다리는 시간의 많은 프로그램들에 있어서는 거의 느낄 수 없을 정도이다.

2.2 자바 가상기계 (Java Virtual Machine)

앞서 자바 가상기계를 CPU에 비교하였다. 자바 가상기계의 기계어에 해당하는 명령어들을 바이트코드라고 부른다. 이는 명령어의 기능을 구분하는 코드(op code)들이 모두 한 바이트이기 때문에 붙여진 이름이다. 사실상 자바의 바이트코드를 하드웨어적으로 구현하는 CPU를 만드는 것이 가능한데 이미 에서는 picoJava라고 불리는 CPU 핵심(core)의 설계를 끝마쳐 두고 있다. 자바 가상기계는 다른 CPU들과 비교했을 때 다음과 같은 특성을 가진다.

썬마이크로시스템즈

특성

Operand stack을 사용하는 stack machine이다. 따라서, 범용 레지스터(register)가 없다.

입출력의 위한 명령어가 없다.

명령어 구분 코드(op code)는 모두 1 바이트이며, 명령어의 길이가 고정되어 있지 않다 (CISC와 유사). 하지만, 평균 명령어 길이가 1.8 바이트로 CISC는 물론이고 명령어의 길이가 4바이트로 고정적인 RISC 계열보다 오히려 코드 크기가 작다.

명령어의 수가 200개 정도로 CISC와 달리 복잡하지 않아 오히려 RISC에 가깝다.(CPU 구현시 Pipelining과 같은 RISC 계열의 기법을 적용할 수 있다)

객체지향 program을 직접적으로 지원하는 고수준의 instruction set이다. 메모리 주소가 아니라 객체 단위의 메모리 접근만을 허용하며 메쏘드 호출을 위한 명령어가 존재한다. (cf. Intel 432, etc)

주소에 의한 직접적인 메모리 접근이 불가능하므로 하드웨어의 도움이 없이도 메모리 영역의 보호가 가능하다. (memory management unit이 필요없다. 즉, 가상메모리 지원이 없어도 된다.)

가베지 콜렉션을 전제로 하며 다중 쓰레드에서의 동기화를 지원하는 명령을 가지고 있다.

설계 목적

위에 열거한 자바 가상기계의 특성은 사실 다음과 같은 점들을 고려하여 설계된 것이다.

보안

불법적인 프로그램인지를 검증하기 쉽게 설계 (bytecode verifier)

네트워크 상에서의 전송 중에 생길 수 있는 오류 검출

입출력 명령이 없으므로 입출력 담당하는 객체에 권한을 설정함으로 보안성 강화 가능(sandbox)

네트워크: 작은 코드 크기, 클래스 단위의 실행중 동적 링크

플랫폼 독립성: 일단 자바 가상기계가 구현되면 하드웨어의 종류에 상관없이 어디서나 바이트코드를 실행할 수 있다.

소프트웨어적인 구현 방법들

현재 JDK에 포함되어 있는 자바 가상기계는 해석기로 구현되어 있어 비교적 속도가 느린 편이다. JDK 1.1에서는 해석기의 일부를 어셈블리로 작성하여 속도를 향상시켰다. 현재까지 속도향상을 위한 가장 보편적인 방법은 JIT(Just-In-Time) 컴파일러라고 불리우는 일종의 해석기를 사용하는 것인데, 벌써 많은 기종에서 JIT 컴파일러가 지원되고 있다. 다음은 자바 가상기계를 소프트웨어적으로 구현하는 다양한 방법에 대해 정리해 본 것이다.

해석기(interpreter): 가장 일반적인 방법으로 다른 플랫폼으로의 이식이 용이하다. 하지만, 속도가 느리다는 단점이 있다.

JIT(Just-In-Time) 컴파일러: 어떤 메쏘드가 수행되는 그 순간에 바이트코드를 자바가 실행되는 실행환경의 기계어로 번역한 뒤 번역된 코드를 실행한다.

현재 윈도즈 환경에서는 마이크로소프트나 시맨텍, 볼랜드 등에 의해 개발되어 있으며, 썬의 솔라리스, 실리콘 그래픽스의 IRIX, IBM의 AIX와 OS/2용도 각 사에서 개발하여 제공하고 있다.

해석기 보다 빠른 속도

자바의 동적인 특성을 그대로 살림

프로그램을 실행하는 도중에 컴파일을 행하므로 충분한 최적화를 할 수 없다.

처음에 바이트코드를 컴파일하는데 걸리는 시간은 해석기의 실행 속도보다 느릴 수 있다.

다른 하드웨어로의 이식이 용이하지 않다.

정적 컴파일러(static compiler): C/C++와 같이 자바 원시코드 내지 바이트코드를 전부 기계어로 컴파일해 둔다.

현재 사의 수퍼시드(SuperCede)가 윈도즈 용으로 나와 있으며, 실리콘 그래픽스의 코스모코드(CosmoCode)에도 유사한 기능이 포함되어 있다.

어시메트릭스(Asymetrix)

JIT 컴파일러보다 최적화된 코드 생성

자바의 동적인 특성을 희생

서버용 소프트웨어, 임베디드(embeded) 시스템 등 속도를 요하는 분야에 적용가능

참고: 어시매트릭스사의 수퍼시드(SuperCede)는 클래스 단위로 컴파일하고 동시에 컴파일된 결과를 디스크에 캐쉬하는 특성을 함께 갖추고 있다.

썬의 핫스팟(HotSpot) 기술: 차세대 자바 가상기계, 실행도중에 얻은 데이터를 바탕으로 성능에 문제가 되는 부분을 찾아서 최적화를 행한다.

[참고 5]

자바원(JavaOne) 컨퍼런스 97에서 발표

자바의 동적인 특성을 버리지 않고 C/C++에 필적하는 성능향상을 얻는 것을 목표

정적 컴파일러의 성능을 능가: 객체지향적 프로그램이 가지는 성능저하 문제를 성공적으로 해결할 것으로 전망

97년말 나올 예정

자바 언어와의 관계

자바 가상기계는 분명히 자바 언어와 밀접한 관계를 가진다. 구조 자체가 객체지향이라는 점과 가베지 콜렉션, 쓰레드 동기화 등을 지원하는 것 등이 바로 그 증거이다. 하지만, 한 CPU 상에서 사용할 수 있는 프로그래밍 언어가 둘 이상일 수 있듯이 자바 가상기계 상에서도 다른 언어를 사용하는 것이 가능하다. 현재 IBM의 라는 언어가 나와 있으며, 그 외에 ADA를 컴파일해주는 컴파일러도 사용되고 있다.

NetRexx

이는 현재 ADA, FORTRAN 등의 다른 언어로 작성된 프로그램을 가지고 있는 단체에서 자바로 옮겨갈 경우 기존에 작성된 프로그램들을 이용할 수 있다는 점에서 중요하다. 또, NetRexx와 같은 언어들은 자바보다는 단순하고 간단한 프로그래밍을 할 경우 유용하다. 썬에서는 차후에 자바 가상기계에서 다른 언어를 사용하는 것이 용이하도록 자바 가상기계의 지원을 확대할 계획이 있다고 한다.

[참고 6]

[참고 7]

2.3 자바 API (Java Application Programming Interface)

앞서 밝힌 바와 같이 자바 API는 자바 플랫폼에 있어서 필수불가결한 요소이다. 하지만, 최초에 발표된 JDK 1.0.2 API는 초기 웹 상에서의 간단한 작업 정도를 지원할 수 있는 수준의 API였고 따라서 자바의 적용범위에 큰 제약이 되어왔다. 이런 이유로 자바에 대한 본격적인 지원이 가속된 뒤, 자바소프트와 컴퓨터 업계의 주된 기업들에 의해 새로운 API가 계속하여 개발되었고 또 개발되고 있다. 아울러 기존 자바 API에 대한 재검토와 보완이 이루어져 왔는데, 이와 같은 노력의 첫 결실이 바로 JDK 1.1 API이다. 현재 다양한 종류의 API들이 개발되고 있으며, 기업의 컴퓨터와 네트워크 전반에서의 적용을 주된 목표로 멀티미디어, 임베디드 시스템 등 다양한 분야로 그 활용범위를 넓혀가고 있다.

자바 API와 보안

현재 자바 라이브러리는 자바상의 보안에 있어서 매우 중요한 요소이다. JDK에 포함된 표준 자바 라이브러리 중 보안에 있어서 위해요소가 있는 파일 입출력, 네트워크 접속 등에 해당하는 API들은 내부에서 java.lang.SecurityManager 객체에 현재 실행할 작업의 적법성 여부를 묻게 되어 있다. 이 때 SecurityManager 객체가 작업의 적법성을 인증하지 않으면 우리가 흔히 애플릿을 띄울 때 만나게 되는 SecurityException이 발생되게 된다. 애플릿이 특정 작업을 행할 수 없는 이유가 바로 웹 브라우저나 appletviewer가 자신에 맞는 SecurityManager를 사용하고 있기 때문다. 반면에 어플리케이션은 특별한 경우가 아니면 이 SecurityManager가 없는 상태에서 수행되므로 어떤 작업이든지 임의로 행할 수 있는 것이다. 이러한 자바의 보안 모델을 "모래상자(sandbox)"모델이라고 한다. 필요에 따라 SecurityManager를 작성하면 다른 보안 정책을 적용시킬 수 있다. 일례로 JDK의 appletviewer가 설정하기 나름으로 특정 파일을 읽고 쓰는 것이 허용되는 것은 넷스케이프와 같은 웹 브라우저와 SecurityManager가 다르기 때문이다.

3. 왜 자바인가?

3.1 네트워크

앞서 언급한 바 있지만 자바는 다음과 같은 이유에서 네트워크를 이용하는 프로그램의 개발에 적합하다.

코드의 크기가 작다. (평균 명령어 길이가 1.8바이트)

전송중 오류나 불법적으로 작성된 코드를 검증할 수 있다. (bytecode verifier)

플랫폼 독립적이다. (이기종으로 구성된 네트워크 상에서 자유로이 옮겨다닐 수 있다)

API상의 네트워크 지원 (URL 클래스, RMI 등)

3.2 플랫폼 독립성

자바 가상기계와 언어자체의 명확한 정의로 한번 자바 실행환경(가상기계와 라이브러리)이 이식되면 어디서나 재컴파일내지 수정이 없이 실행할 수 있다. 일반적으로 소프트웨어 개발시 여러 플랫폼을 지원하는데 드는 비용을 없앨 수 있다.

3.3 생산성 및 신뢰도 향상

객체 지향

동적 링크 - 컴파일, 디버깅 등의 개발 과정에서 반복되는 작업을 최소화할 수 있다.

가베지 콜렉션 - 메모리 오류 제거

예외 처리

언어의 단순성

플랫폼 독립성 - 여러 플랫폼 지원하는데 드는 자원 분산이 없다.

4. JDK 1.1

JDK의 버전(version)은 '.'을 구분으로 세 개의 숫자로 이루어져 있다. 이 중 마지막 숫자는 그 전 버전의 오류를 수정한 오류 수정판인 경우에 증가된다. 이 글이 작성되는 현재 JDK 1.1.1까지 나와있는데 이는 JDK 1.1의 오류를 수정했음을 뜻한다. 다음으로 가운데 숫자는 기능상의 추가가 있었을 경우 하나씩 증가된다. JDK 1.0에서 JDK 1.1로 가면서 API상의 기능 추가와 자바 언어 자체의 변화가 있었음을 상기하기 바란다. 이 경우 이전 버전에서 동작하던 프로그램들과 최소한 상위 호환성을 유지하게 된다. 그리고 마지막으로 처음 숫자는 자바 자체에 상당한 변화가 있을 경우에 증가하게 되는데, 이 경우 이전까지 작성된 프로그램들은 새 버전에서는 동작하지 않을 수도 있다. 즉, 이진 호환성(binary compatibility)이 보장되지 않을 수 있다. 현재 JDK 1.1이라고 하면 기능상 JDK 1.0과 구분되는 자바 버전을 지칭하는 것으로 이 글이 쓰여지는 시점에서는 JDK 1.1.1이 가장 최근의 오류 수정판이다.

[참고 4]

앞으로 설명하는 내용에 별도의 강의가 준비되어 있는 자바빈즈(JavaBeans)와 RMI(Remote Method Invocation), JDBC 등의 내용은 포함하지 않았다. 또, 크게 중요하지 않다고 생각되는 세부적인 사항은 생략하였다. 자 그럼 JDK 1.1에서 지원하는 새로운 기능들을 살펴보도록 하자.

국제화(Internationalization)

국제화는 프로그램의 작성시 사용자의 문화나 관습 혹은 언어에 따라 틀려질 수 있는 부분을 효과적으로 분리시키는 것을 뜻한다. 이렇게 작성된 프로그램들은 쉽게 특정 나라나 언어에 맞게 수정될 수 있게 된다. 자바에서는 이러한 국제화된 프로그램의 작성을 용이하게 하기 위한 새로운 API를 제공하는데, 유니코드를 지원하는 자바의 특성상 한 프로그램안에서 동시에 여러 언어를 사용하는 것이 용이하도록 하고 있다.

윈도즈나 유닉스의 국제화 지원이 시스템 전체에 언어나 관습 등을 통칭하는 로케일(locale)을 설정하도록 하고 있는데 비해 자바는 이 로케일을 객체 단위로 설정하도록 되어 있다. 따라서, 자바 내부에서 제공되는 국제화를 지원하기 위한 객체들도 어떤 로케일이 주어지느냐에 따라 각기 다른 로케일을 지원할 수 있도록 하고 있다.

import java.util.*;

import java.text.*;

Locale us = new Locale("en", "US");

Collator usCollator = Collator.getInstance(us);

usCollator.setStrength(Collator.PRIMARY);

if( usCollator.compare("abc", "ABC") == 0 ) {

System.out.println("Strings are equivalent");

}

위의 예에서 보는 바와 같이 모든 국제화된 객체들은 java.util.Locale 객체를 받아서 그에 맞도록 움직여야 한다.

보안 및 디지탈 서명된 애플릿(Security and Signed Applets)

JDK 1.0.2까지는 애플릿이 행할 수 있는 일에 많은 제약이 있었다. 파일 입출력은 물론이고 네트워크 연결까지 마음대로 할 수 없었다. JDK 1.1에는 전자서명 및 메시지 다이제스트(message digest)까지 보안 관련 API가 추가 되었고 전자서명된 애플릿은 애플릿을 실행하는 쪽에서 인증할 경우 SecurityManager가 없는 것 같이 어떠한 일이라도 할 수 있도록 허용될 수 있다. 이 기능은 앞으로는 전자서명으로 인지된 대상마다 권한을 보다 세밀하게 제어할 수 있도록 보강될 예정이라고 한다.

AWT 개선

자바의 GUI(Graphical User Interface) 툴킷인 AWT는 상업적으로 판매하는 수준의 소프트웨어를 작성하는데 있어서 가장 큰 걸림돌 중에 하나였다. 최근 넷스케이프에 내어 놓은 IFC(Internet Foundation Classes)로 AWT를 보충하는 수준에서 많은 개선이 이루어지자 AWT 자체에서도 이러한 변화를 수용하기 시작하였다. 현재 JDK 1.1에 포함된 기능 외에 앞으로 썬과 넷스케이프 그리고 IBM이 공동으로 IFC와 AWT를 통합하는 JFC(Java Foundation Classes)라는 새로운 GUI 툴킷을 내어 놓을 예정이라고 한다.

현재 JDK 1.1 AWT에서는 순수하게 자바로 소프트웨어적으로 구현되는 GUI 컴포넌트인 경량 컴포넌트(lightweight component)를 지원하도록 java.awt.Component, java.awt.Container를 상속받아 수정할 수 있도록 하고 있다. 하지만, JDK 1.1에는 경량 컴포넌트로 구현된 버튼 등의 GUI 컴포넌트는 포함되어 있지 않다. 지금까지의 자바 컴포넌트들이 윈도즈나 X 윈도 상의 GUI 부품과 1대 1로 연결되어 이 들 고유 컴포넌트들과 자바를 연결하는 역할을 했던데 비해, 경량 컴포넌트는 하나의 윈도 안에서 순수하게 자바 코드로만 컴포넌트의 이벤트를 처리하고 컴포넌트를 그려주도록 작성된다는 점에서 틀리다. X/Motif의 개짓(Gadget)과 유사한 개념이라고 생각하면 이해가 쉬울 것이다. 경량 컴포넌트는 자바가 수행되는 운영체제나 하드웨어에 상관없이 똑같은 모양의 GUI를 구성할 수 있고, 상대적으로 속도가 빠르다는 점에서 잇점이 있다. 또한, 뒷 배경이 비쳐보이는 투명한 컴포넌트를 만들 수 있다는 장점도 있다.

다음으로 AWT상의 이벤트 처리 방식이 바뀌었다. 이전까지는 마우스, 키 등 모든 이벤트가 항상 해당 컴포넌트에 전달되었으나 JDK 1.1에서는 이를 미리 선택하도록 하여 불필요한 이벤트가 전혀 전달되지 않도록 함으로 불필요한 이벤트로 인한 성능 저하를 방지할 수 있다. 또한, 위임(delegation) 이벤트 모델이라는 새로운 개념을 도입하였다. 지금까지의 AWT 프로그래밍은 사용하는 컴포넌트를 상속해서 이벤트를 전달받는 메쏘드를 재정의하는 방식을 사용하였는데, GUI 쪽 코드와 다른 프로그램 코드가 지나치게 연관되는 단점이 있었다. 이러한 이유로 큰 프로그램을 작성하거나 빈번히 GUI를 수정하는 프로그램을 작성하거나 하는 경우 문제가 있었다. 다음은 위임 이벤트 모델을 사용하는 예제로 자바소프트의 사이트에서 빌려온 것이다.

import java.awt.*;

import java.awt.event.*;

public class App {

public void search() {

/* do search operation ...*/

System.out.println("Searching...");

}

public void sort() {

/* do sort operation ...*/

System.out.println("Sorting....");

}

static public void main(String args[]) {

App app = new App();

GUI gui = new GUI(app);

}

}

class Command implements ActionListener  {

static final int SEARCH = 0;

static final int SORT = 1;

int id;

App app;

public Command(int id, App app) {

this.id = id;

this.app = app;

}

public void actionPerformed(ActionEvent e) {

switch(id) {

case SEARCH:

app.search();

break;

case SORT:

app.sort();

break;

}

}

}

class GUI {

public GUI(App app) {

Frame f = new Frame();

f.setLayout(new FlowLayout());

Command searchCmd = new Command(Command.SEARCH, app);

Command sortCmd = new Command(Command.SORT, app);

Button b;

f.add(b = new Button("Search"));

b.addActionListener(searchCmd);

f.add(b = new Button("Sort"));

b.addActionListener(sortCmd);

List l;

f.add(l = new List());

l.add("Alphabetical");

l.add("Chronological");

l.addActionListener(sortCmd);

f.pack();

f.show();

}

}

예제에서 보는 바와 같이 컴포넌트 자체를 확장시키는 경우를 제외하고는 컴포넌트를 상속받지 않아도 된다. 이벤트는 위임 받은 객체들에게로 전달됨을 알 수 있다.

또한 키보드를 지름길이라든지 내부적으로 이미지 처리를 개선한든지 하는 변화가 있었으며, 스크롤 페인(scroll pane), 팝업 메뉴(popup menu)등 새로운 컴포넌트와 클립보드에 대한 지원도 추가 되었다.

JAR (Java ARchive) 파일

자바 바이트코드의 크기가 작다고는 하지만, 동적 링크라는 특성상 메쏘드 이름 등의 부가적인 정보가 많아져서 사실 클래스 파일의 전체적인 크기는 무시못할 정도로 크다. 또한 HTTP 자체가 하나의 클래스마다 별도의 TCP 연결을 행하는 관계로 클래스의 갯수가 많아지만 클래스 파일의 갯수도 늘고 따라서 전송 속도도 떨어지는 문제가 있었다. JAR는 클래스 파일을 포함하여 이미지 파일 등의 여러가지 파일을 묶고 압축하고 전자 서명할 수 있는 수단을 제공한다.

객체지향 프로그램의 특성상 프로그램을 되도록 작은 클래스들로 나누게 되고, JDK 1.1에서는 이너 클래스(inner class)라는 새로운 개념을 내어 놓아 클래스 파일을 갯수가 늘어날 소지가 높아졌으므로 전송효율상으로 보았을 때 JAR 파일은 매우 중요하다. 현재 썬 소프트에서 솔라리스에 탑재하기 위해 발표한 JDK 1.1 JIT 컴파일러 패키지는 아예 자바 클래스 라이브러리를 JAR로 묶어서 제공하고 있다.

입출력 기능 확장

이전까지의 자바 입출력 라이브러리의 문제점은 유니코드의 입출력이나 유니코드와 자바가 실행되는 환경에서 사용하는 문자 코드간의 변환을 효과적으로 다룰 수 있는 메쏘드가 없었다는 것이었다. JDK 1.1은 문자 스트림(character stream) 계열의 클래스를 추가하여 쉽게 유니코드로 된 파일이나 데이터를 입출력할 수 있도록 하였다.

Math 패키지

임의의 크기의 숫자를 다루기 위해 BigInteger와 BigDecimal 클래스가 추가 되었다.

객체 순차화(Object Serialization)

객체를 스트림화하여 파일에 저장하고 또 필요에 따라 다시 저장된 원래 객체를 복원하는 기능이다. 현재 RMI(Remote Method Invocation)에서 메쏘드의 인자를 네트워크 상으로 전송하기 위해서 사용하고 있다. 객체를 데이터베이스에 저장하거나 네트워크로 현재 상태 그대로 객체를 주고 받는다든지 하는 경우 사용될 수 있다. 다음 예는 자바소프트의 문서에서 옮겨온 것이다.

// Serialize today's date to a file.

FileOutputStream f = new FileOutputStream("tmp");

ObjectOutput s = new ObjectOutputStream(f);

s.writeObject("Today");

s.writeObject(new Date());

s.flush();

// Deserialize a string and date from a file.

FileInputStream in = new FileInputStream("tmp");

ObjectInputStream s = new ObjectInputStream(in);

String today = (String)s.readObject();

Date date = (Date)s.readObject();

리플렉션(Reflection)

메쏘드의 이름이나 필드의 이름을 문자열로 계산하여 해당 메쏘드를 호출하거나 필드를 사용할 수 있도록 하는 기능이다. 자바빈즈 등에서 사용되기 위해서 개발되었다.

이너 클래스(Inner Classes)

클래스 내부에 클래스를 정의하여 사용할 수 있게 하는 것으로 어뎁터(adapter) 객체라고 불리는 프로그래밍 스타일을 지원하기 위해서 추가되었다. 바이트코드 검사기(bytecode verifier)의 일부 수정을 제외하고는 사실상 자바 가상기계의 수정이 필요없도록 구현하고 있다. 어뎁터는 쉽게 이야기하면 일종의 콜백(callback) 함수와 비슷한 기능을 하는 객체라고 생각하면 된다. 이 이너 클래스로부터 생성된 객체는 객체를 생성시킨 객체와 연관되어 사용된다. 다음은 자바소프트의 문서에서 옮겨온 예제이다.

public class FixedStack {

Object array[];

int top = 0;

FixedStack(int fixedSizeLimit) {

array = new Object[fixedSizeLimit];

}

public void push(Object item) {

array[top++] = item;

}

public boolean isEmpty() {

return top == 0;

}

// other stack methods go here...

/** This adapter class is defined as part of its target class,

*  It is placed alongside the variables it needs to access.

*/

class Enumerator implements java.util.Enumeration {

int count = top;

public boolean hasMoreElements() {

return count > 0;

}

public Object nextElement() {

if (count == 0)

throw new NoSuchElementException("FixedStack");

return array[--count];

}

}

public java.util.Enumeration elements() {

return new Enumerator();

}

}

이너 클래스인 Enumerator 객체는 둘러싸고 있는 FixedStack 객체의 필드를 임의로 사용할 수 있다. FixedStack 클래스에서 나온 객체가 몇개이든지 그 안에서 생성된 Enumerator 객체는 자신을 생성시킨 FixedStack 객체의 필드나 메쏘드를 참조하게 된다는 점을 명심하자. 이런 면에서 단순히 C++에서 클래스를 중첩시키는 것과는 틀리다.

Java Native Interface

C/C++로 고유 코드를 작성하는 규약이다. 표준으로 제정되었으므로 최소한 자바 가상기계가 어떻게 구현되었나에 상관없이 동일한 고유코드 라이브러리를 연결하여 사용할 수 있다는 점에서 중요한 의미를 가진다. 현재 JDK 1.1의 AWT 등의 라이브러리도 이 JNI에 준하여 작성되었으므로 혹 누군가 JNI를 지원하는 자바 가상기계를 만든다면 별도로 AWT를 이식할 필요가 없이 곧바로 사용할 수 있을 것이다. 이런 고유 코드 작성 규약 외에 JNI를 사용하면 자바 가상기계를 C/C++ 프로그램 내에서 사용할 수도 있다.

4. 결 론

자바는 아직 완전히 성숙하지는 못했다고 생각한다. 하지만, 2년이란 짧은 시간 동안 얼마나 많은 개선이 있었는가를 생각하면 기대해 봄직한 면들이 많다고 자신있게 이야기할 수 있다.

자바는 소프트웨어의 생산성과 신뢰도를 높여주는 좋은 특징을 가지고 있다.

자바는 이종의 컴퓨터가 물려있는 현대 네트워크 상에서 동작하는 소프트웨어를 개발하는데 최적이다.

자바 가상기계의 속도는 다양한 방법으로 향상되어가고 있고 실질적인 문제를 해결하는데 있어서 충분하다.

새로운 자바 API의 개발로 자바의 활용범위는 더욱 넓어져가고 있다.

5. 참고자료

[1] 애플릿에 대한 보안상의 제약 ()

http://www.javasoft.com:80/sfaq/#applets

[2] 월간 마이크로소프트웨어 96년 8월 자바 프로그래밍[7], pp 528~539

[3] 넷스케이프 4.0 FAQ ()

http://home.netscape.com/comprod/products/communicator/faq.html#access

[4] JDK 1.1과 그 이전 버전과의 호환성 문제 ()

http://www.javasoft.com/products/jdk/1.1/compatibility.html

[5] 자바원 97 컨퍼런스 슬라이드 - Breaking the Speed Barrier: The Future of Java Performance ()

http://www.javasoft.com/javaone/sessions/slides/TT06/griswold.htm

[6] 월간 마이크로소프트웨어 97년 4월 특집 1부 "97년, 자바의 향기는 그윽하다", pp 247, NASA의 고다드 우주비행 센터에서의 자바 적용 예

[7] Tim Lindholm and Frank Yellin, "Java Virtual Machine Specification" , Addison-Wesley, 1996

[8] 자바소프트 JDK 1.1 문서 ()

http://www.javasoft.com:80/products/jdk/1.1/docs/index.html