JDK 1.1 Tutorial자바는 일반적인 인식과는 달리 프로그래밍 언어, 가상기계, 그리고, 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가 포함되어야 하는 것이다.
JDK(Java Development Kit)는 자바 프로그램을 개발하고 실행할 수 있는 도구의 집합이다. 현재 썬의 자회사인 자바소프트(Javasoft)에서 무료로 배포하고 있는 JDK에는 자바 가상기계가 "java"라는 이름의 해석기(interpreter) 프로그램으로 구현되어 있으며, 그 외에 자바 원시코드를 바이트코드로 컴파일해 주는 컴파일러인 "javac"와 디버거인 "jdb" 등의 개발 도구가 함께 포함되어 있다. 보통 마이크로소프트의 "비쥬얼 J++(Visual J++)", 시맨텍의 "카페"와 같은 자바 개발도구나 넷스케이프, 마이크로소프트의 웹 브라우저에 포함되는 자바 가상기계와 라이브러리들은 JDK에 포함된 것을 기본으로 개선을 위해 일부 수정된 것들이다.
최근 JDK 1.1이 나오면서 자바소프트에서는 JDK외에 JRE(Java Runtime Environment)라는 별도의 패키지를 배포하기 시작했다. 이는 JDK에서 자바 프로그램을 수행하기 위해 필수적인 부분만을 모은 것으로 자바로 프로그램을 작성한 사람이 자신의 프로그램과 함께 로얄티 없이 배포할 수 있도록 제공되는 것이다. 프로그램을 작성하기 위한 "javac", "jdb"와 같은 도구들은 제외되어 있고 자바 가상기계와 라이브러리 측면에서는 JDK와 동일하다. 마이크로소프트에서도 이와 유사하게 자사의 자바 SDK(Software Development Kit)의 일부를 JRE와 유사한 조건으로 배포할 수 있도록 하고 있다.
애플릿은 HTML 페이지에 포함되어 자바 가상기계 및 라이브러리를 탑재한 웹 브라우저 상에서 실행되는 자바 프로그램을 말한다. 네트워크를 통해서 원거리에 있는 서버로부터 애플릿을 구성하는 자바 바이트코드를 전달받아 수행하는 구조이며, 초창기 대부분의 자바 프로그램들이 이 부류에 속한다. 이에 비해 어플리케이션은 흔히 사용하는 워드프로세서 등의 프로그램과 같이 독립적으로 수행되는 자바 프로그램을 지칭하는 용어로 보통 JDK, JRE에 포함된 자바 실행환경을 사용하여 실행시킨다.
애플릿은 일반적으로 네트워크를 통해 전송되므로 전송속도를 감안해서 크기가 작은 것이 보통이며, 인터넷상의 불특정 서버로부터 애플릿을 전송받아 실행하는 경우가 많으므로 어플리케이션에 비해 보안에 관련된 제약이 많은 편이다. 현재 넷스케이프를 포함한 대다수의 웹 브라우저에서는 현재 JDK 1.0.2와 동일한 규격의 자바 실행환경을 탑재하고 있는데 이들 브라우저 상에서는 애플릿에 대해 다음과 같은 제약을 가하고 있다.
구체적인 내용은 [참고 1]을 참고하기 바란다. 이런 이유로 애플릿이 데이터를 저장하고자 할 때는 애플릿을 제공하고 있는 서버측에 네트워크 연결을 해서 서버측의 파일에 정보를 저장해야 한다. CGI를 쓰거나 별도의 서버를 작성하는 방법이 있는데, 이에 대한 자세한 설명과 예제는 [참고 2]를 참고하기 바란다. 뒤에 언급할 JDK 1.1에서는 전자서명을 이용하여 특정 애플릿에게 추가적인 권한을 줄 수 있게 하고 있으며, 최근 발표에 따르면 앞으로 넷스케이프나 인터넷 익스플로러와 같은 웹 브라우저에서도 사용자 확인하에 애플릿이 파일 입출력 등의 추가적인 권한을 가질 수 있도록 할 것이라고 한다 [참고 3].
일반적으로 애플릿과 어플리케이션을 구분하지만, 위에 언급한 제약을 제외하면 실행되는 방법의 차이가 있을 뿐 근본적으로 애플릿과 어플리케이션은 그 능력에 있어서 차이가 없다. 애플릿이 웹 페이지 상에 그림과 같이 영역을 차지하기는 하지만 어플리케이션과 마찬가지로 별도로 윈도를 띄울 수 있으며, 전자서명 등의 방법으로 허가를 얻으면 파일 입출력이나 네트워크 연결도 자유로이 행할 수 있다. 앞으로 네트워크 컴퓨터가 일반화되면 대부분의 응용프로그램들은 웹 페이지 상에서 애플릿의 형태로 제공될 것이다. 이런 인트라넷(intranet) 환경에서는 전송 시간이 큰 문제가 되지 않을 것으므로 애플릿으로 제공되는 프로그램의 크기 또한 문제가 되지 않을 것이다.
자바는 네트워크를 위한 언어라고 일컫어진다. 이는 API상의 네트워크 지원과 함께, 애플릿과 같이 네트워크를 통해 실행파일이 옮겨다니는데 있어서 여러가지로 좋은 특성을 가지고 있음에 기인한다. 마이크로소프트의 액티브 X와 같은 기술과 비교할 때, 전송시의 효율, 안전성, 그리고, 실행시의 보안 문제 등에 있어서 월등히 뛰어나다. 이에 대해서는 뒤에 자세히 언급하도록 하겠다.
자바 프로그래밍 언어는 C/C++의 문법을 기본으로 Eiffel, SmallTalk, Objective C, Cedar/Mesa 등의 언어를 참고하여 개발되었다. 초기의 C 언어가 그랬듯이 자바는 객체지향 언어이면서도 언어자체는 무척 간단하다. 다음은 C/C++를 염두에 두고 자바 언어의 특징을 정리해 본 것이다.
특히 위에서 포인터가 없고, 배열에서 범위 검사를 행하며, 가베지 콜렉션을 행하는다는 특성은 일반적으로 C/C++로 프로그래밍하는 경우 부딪히는 대부분의 오류인 메모리 오류를 대폭 제거할 수 있다는 점에서 매우 중요하다. 가베지 콜렉션은 가장 낮은 순위로 실행되고 있는 별도의 쓰레드에 의해 행해지므로 보통 사용자 입력을 기다리는 시간의 많은 프로그램들에 있어서는 거의 느낄 수 없을 정도이다.
앞서 자바 가상기계를 CPU에 비교하였다. 자바 가상기계의 기계어에 해당하는 명령어들을 바이트코드라고 부른다. 이는 명령어의 기능을 구분하는 코드(op code)들이 모두 한 바이트이기 때문에 붙여진 이름이다. 사실상 자바의 바이트코드를 하드웨어적으로 구현하는 CPU를 만드는 것이 가능한데 이미 썬마이크로시스템즈에서는 picoJava라고 불리는 CPU 핵심(core)의 설계를 끝마쳐 두고 있다. 자바 가상기계는 다른 CPU들과 비교했을 때 다음과 같은 특성을 가진다.
위에 열거한 자바 가상기계의 특성은 사실 다음과 같은 점들을 고려하여 설계된 것이다.
현재 JDK에 포함되어 있는 자바 가상기계는 해석기로 구현되어 있어 비교적 속도가 느린 편이다. JDK 1.1에서는 해석기의 일부를 어셈블리로 작성하여 속도를 향상시켰다. 현재까지 속도향상을 위한 가장 보편적인 방법은 JIT(Just-In-Time) 컴파일러라고 불리우는 일종의 해석기를 사용하는 것인데, 벌써 많은 기종에서 JIT 컴파일러가 지원되고 있다. 다음은 자바 가상기계를 소프트웨어적으로 구현하는 다양한 방법에 대해 정리해 본 것이다.
자바 가상기계는 분명히 자바 언어와 밀접한 관계를 가진다. 구조 자체가 객체지향이라는 점과 가베지 콜렉션, 쓰레드 동기화 등을 지원하는 것 등이 바로 그 증거이다. 하지만, 한 CPU 상에서 사용할 수 있는 프로그래밍 언어가 둘 이상일 수 있듯이 자바 가상기계 상에서도 다른 언어를 사용하는 것이 가능하다. 현재 IBM의 NetRexx라는 언어가 나와 있으며, 그 외에 ADA를 컴파일해주는 컴파일러도 사용되고 있다.
이는 현재 ADA, FORTRAN 등의 다른 언어로 작성된 프로그램을 가지고 있는 단체에서 자바로 옮겨갈 경우 기존에 작성된 프로그램들을 이용할 수 있다는 점에서 중요하다[참고 6]. 또, NetRexx와 같은 언어들은 자바보다는 단순하고 간단한 프로그래밍을 할 경우 유용하다. 썬에서는 차후에 자바 가상기계에서 다른 언어를 사용하는 것이 용이하도록 자바 가상기계의 지원을 확대할 계획이 있다고 한다[참고 7].
앞서 밝힌 바와 같이 자바 API는 자바 플랫폼에 있어서 필수불가결한 요소이다. 하지만, 최초에 발표된 JDK 1.0.2 API는 초기 웹 상에서의 간단한 작업 정도를 지원할 수 있는 수준의 API였고 따라서 자바의 적용범위에 큰 제약이 되어왔다. 이런 이유로 자바에 대한 본격적인 지원이 가속된 뒤, 자바소프트와 컴퓨터 업계의 주된 기업들에 의해 새로운 API가 계속하여 개발되었고 또 개발되고 있다. 아울러 기존 자바 API에 대한 재검토와 보완이 이루어져 왔는데, 이와 같은 노력의 첫 결실이 바로 JDK 1.1 API이다. 현재 다양한 종류의 API들이 개발되고 있으며, 기업의 컴퓨터와 네트워크 전반에서의 적용을 주된 목표로 멀티미디어, 임베디드 시스템 등 다양한 분야로 그 활용범위를 넓혀가고 있다.
현재 자바 라이브러리는 자바상의 보안에 있어서 매우 중요한 요소이다. JDK에 포함된 표준 자바 라이브러리 중 보안에 있어서 위해요소가 있는 파일 입출력, 네트워크 접속 등에 해당하는 API들은 내부에서 java.lang.SecurityManager 객체에 현재 실행할 작업의 적법성 여부를 묻게 되어 있다. 이 때 SecurityManager 객체가 작업의 적법성을 인증하지 않으면 우리가 흔히 애플릿을 띄울 때 만나게 되는 SecurityException이 발생되게 된다. 애플릿이 특정 작업을 행할 수 없는 이유가 바로 웹 브라우저나 appletviewer가 자신에 맞는 SecurityManager를 사용하고 있기 때문다. 반면에 어플리케이션은 특별한 경우가 아니면 이 SecurityManager가 없는 상태에서 수행되므로 어떤 작업이든지 임의로 행할 수 있는 것이다. 이러한 자바의 보안 모델을 "모래상자(sandbox)"모델이라고 한다. 필요에 따라 SecurityManager를 작성하면 다른 보안 정책을 적용시킬 수 있다. 일례로 JDK의 appletviewer가 설정하기 나름으로 특정 파일을 읽고 쓰는 것이 허용되는 것은 넷스케이프와 같은 웹 브라우저와 SecurityManager가 다르기 때문이다.

앞서 언급한 바 있지만 자바는 다음과 같은 이유에서 네트워크를 이용하는 프로그램의 개발에 적합하다.
자바 가상기계와 언어자체의 명확한 정의로 한번 자바 실행환경(가상기계와 라이브러리)이 이식되면 어디서나 재컴파일내지 수정이 없이 실행할 수 있다. 일반적으로 소프트웨어 개발시 여러 플랫폼을 지원하는데 드는 비용을 없앨 수 있다.
JDK의 버전(version)은 '.'을 구분으로 세 개의 숫자로 이루어져 있다. 이 중 마지막 숫자는 그 전 버전의 오류를 수정한 오류 수정판인 경우에 증가된다. 이 글이 작성되는 현재 JDK 1.1.1까지 나와있는데 이는 JDK 1.1의 오류를 수정했음을 뜻한다. 다음으로 가운데 숫자는 기능상의 추가가 있었을 경우 하나씩 증가된다. JDK 1.0에서 JDK 1.1로 가면서 API상의 기능 추가와 자바 언어 자체의 변화가 있었음을 상기하기 바란다. 이 경우 이전 버전에서 동작하던 프로그램들과 최소한 상위 호환성을 유지하게 된다. 그리고 마지막으로 처음 숫자는 자바 자체에 상당한 변화가 있을 경우에 증가하게 되는데, 이 경우 이전까지 작성된 프로그램들은 새 버전에서는 동작하지 않을 수도 있다. 즉, 이진 호환성(binary compatibility)이 보장되지 않을 수 있다.[참고 4] 현재 JDK 1.1이라고 하면 기능상 JDK 1.0과 구분되는 자바 버전을 지칭하는 것으로 이 글이 쓰여지는 시점에서는 JDK 1.1.1이 가장 최근의 오류 수정판이다.
앞으로 설명하는 내용에 별도의 강의가 준비되어 있는 자바빈즈(JavaBeans)와 RMI(Remote Method Invocation), JDBC 등의 내용은 포함하지 않았다. 또, 크게 중요하지 않다고 생각되는 세부적인 사항은 생략하였다. 자 그럼 JDK 1.1에서 지원하는 새로운 기능들을 살펴보도록 하자.
국제화는 프로그램의 작성시 사용자의 문화나 관습 혹은 언어에 따라 틀려질 수 있는 부분을 효과적으로 분리시키는 것을 뜻한다. 이렇게 작성된 프로그램들은 쉽게 특정 나라나 언어에 맞게 수정될 수 있게 된다. 자바에서는 이러한 국제화된 프로그램의 작성을 용이하게 하기 위한 새로운 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 객체를 받아서 그에 맞도록 움직여야 한다.
JDK 1.0.2까지는 애플릿이 행할 수 있는 일에 많은 제약이 있었다. 파일 입출력은 물론이고 네트워크 연결까지 마음대로 할 수 없었다. JDK 1.1에는 전자서명 및 메시지 다이제스트(message digest)까지 보안 관련 API가 추가 되었고 전자서명된 애플릿은 애플릿을 실행하는 쪽에서 인증할 경우 SecurityManager가 없는 것 같이 어떠한 일이라도 할 수 있도록 허용될 수 있다. 이 기능은 앞으로는 전자서명으로 인지된 대상마다 권한을 보다 세밀하게 제어할 수 있도록 보강될 예정이라고 한다.
자바의 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)등 새로운 컴포넌트와 클립보드에 대한 지원도 추가 되었다.
자바 바이트코드의 크기가 작다고는 하지만, 동적 링크라는 특성상 메쏘드 이름 등의 부가적인 정보가 많아져서 사실 클래스 파일의 전체적인 크기는 무시못할 정도로 크다. 또한 HTTP 자체가 하나의 클래스마다 별도의 TCP 연결을 행하는 관계로 클래스의 갯수가 많아지만 클래스 파일의 갯수도 늘고 따라서 전송 속도도 떨어지는 문제가 있었다. JAR는 클래스 파일을 포함하여 이미지 파일 등의 여러가지 파일을 묶고 압축하고 전자 서명할 수 있는 수단을 제공한다.
객체지향 프로그램의 특성상 프로그램을 되도록 작은 클래스들로 나누게 되고, JDK 1.1에서는 이너 클래스(inner class)라는 새로운 개념을 내어 놓아 클래스 파일을 갯수가 늘어날 소지가 높아졌으므로 전송효율상으로 보았을 때 JAR 파일은 매우 중요하다. 현재 썬 소프트에서 솔라리스에 탑재하기 위해 발표한 JDK 1.1 JIT 컴파일러 패키지는 아예 자바 클래스 라이브러리를 JAR로 묶어서 제공하고 있다.
이전까지의 자바 입출력 라이브러리의 문제점은 유니코드의 입출력이나 유니코드와 자바가 실행되는 환경에서 사용하는 문자 코드간의 변환을 효과적으로 다룰 수 있는 메쏘드가 없었다는 것이었다. JDK 1.1은 문자 스트림(character stream) 계열의 클래스를 추가하여 쉽게 유니코드로 된 파일이나 데이터를 입출력할 수 있도록 하였다.
임의의 크기의 숫자를 다루기 위해 BigInteger와 BigDecimal 클래스가 추가 되었다.
객체를 스트림화하여 파일에 저장하고 또 필요에 따라 다시 저장된 원래 객체를 복원하는 기능이다. 현재 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();
메쏘드의 이름이나 필드의 이름을 문자열로 계산하여 해당 메쏘드를 호출하거나 필드를 사용할 수 있도록 하는 기능이다. 자바빈즈 등에서 사용되기 위해서 개발되었다.
클래스 내부에 클래스를 정의하여 사용할 수 있게 하는 것으로 어뎁터(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++에서 클래스를 중첩시키는 것과는 틀리다.
C/C++로 고유 코드를 작성하는 규약이다. 표준으로 제정되었으므로 최소한 자바 가상기계가 어떻게 구현되었나에 상관없이 동일한 고유코드 라이브러리를 연결하여 사용할 수 있다는 점에서 중요한 의미를 가진다. 현재 JDK 1.1의 AWT 등의 라이브러리도 이 JNI에 준하여 작성되었으므로 혹 누군가 JNI를 지원하는 자바 가상기계를 만든다면 별도로 AWT를 이식할 필요가 없이 곧바로 사용할 수 있을 것이다. 이런 고유 코드 작성 규약 외에 JNI를 사용하면 자바 가상기계를 C/C++ 프로그램 내에서 사용할 수도 있다.
자바는 아직 완전히 성숙하지는 못했다고 생각한다. 하지만, 2년이란 짧은 시간 동안 얼마나 많은 개선이 있었는가를 생각하면 기대해 봄직한 면들이 많다고 자신있게 이야기할 수 있다.
[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)