자바는 쓰레드 모델 기반의 언어입니다. 공유 메모리는 프로세스 기반의 모델에서 서로간의 자원을 공유하여 효율적으로 사용하기 위한 것인데, 쓰레드 자체가 하나의 프로세스에서 자원을 공유하여 사용하는 시분할처리의 개념이므로 기본적으로 ‘자바에서 메모리를 관리하고 실행하는 것 자체가 모두 공유메모리를 사용하고 있다’고 보시면 됩니다. 따라서 자바에는 ‘공유메모리’라는 개념자체가 없습니다. 왜냐면, 기본적으로 사용할 수 있는 것이 공유메모리 밖에 없으니까요.
만약 이런 모델이 아니라면 가비지 컬렉터(GC)도, 동적 클래스 로더도 존재할 수 없을 겁니다. 자바에서는 프로세스는 단 하나, JVM이라고 부르는 가상머신 프로세스 하나뿐입니다. 음, 그렇다면 여러개의 JVM 프로세스 간에 리소스 공유는 어떻게 하느냐? 라고 물으신다면, 현재로서는 답이 없군요. 만약 JVM 레벨의 조작을 허용하면 보안이나 안정성 문제가 발생할테니까요. 그래서 가능하면 JVM을 여러개 띄우지않고 하나의 JVM에서 여러가지의 애플리케이션을 호출하는 편이 좋습니다.
JDK 7에서는 모든 애플리케이션을 하나의 JVM에서 실행할 수 있도록 Isolation API라는 것을 고려하고 있다고 하더군요. 이미 제안은 나온 상태인데, 구현이 안되었을 뿐이죠. 만약 구현된다면 여러개의 애플리케이션을 하나의 머신에서 동작시킬 때 지금과는 비교할 수 없을정도로 효율적인 자원 사용을 할 수 있게 되겠지요.
P.S : 위에 분이 JNI로 구현을 한다고 하셨는데, JNI로 구현을 해서 메모리 영역을 확보해도 그건 자바에서 사용할 수 있는 영역이 아닙니다. JNI는 어디까지나 네이티브 언어와 자바 사이의 교류 역할을 할 뿐이고 자바객체는 어디까지나 JVM의 영역 안에서만 존재할 수 있으니까요. 애시당초, 자바언어의 입장에서는 공유메모리를 따로 확보할 필요가 없습니다.
Shared Memory는 프로세스간의 메모리 공유에 쓰입니다만, 아시다피시 자바 어플리케이션은 JVM 안에서만 존재할 수 있으며 JVM 자체가 하나의 프로세스입니다. 실행되는 어플리케이션은 모두 쓰레드이지요. 가장 중요한 것은 JVM은 보안이나 안정성을 이유로 JVM 외부에 대한 직접적인 접근을 ‘원칙적으로 허용하지 않는다’는 것 입니다. 이것을 허용하게 되면 자바의 철학인 Write Once, Run Anywhere가 깨져버리는데, 썬 입장에서는 용납될 수 없는 일이겠죠.
따라서 다른 프로세스 – 하물며 그 프로세스가 모두 JVM이더라도 – 간의 메모리 공유에 사용되는 방법은 전통적으로 ‘파일’이었습니다. 질문하신 분께서도 같은 의미로 쓰셨다고 생각합니다만 Memory Mapped File 입니다. MMF를 사용할 때 같은 지점의 메모리를 읽어들이는 것이 맞느냐-라고 물어보셨는데… 글쎄요. 맞을 수도, 틀릴 수도 있습니다.
원인을 들어보자면…
첫째, 운영체제의 디스크 운영전략에 따라서 즉각적인 ‘쓰기’가 이루어지지 않을 수도 있습니다.
예를 들어 버퍼링이 있겠지요. NIO에서는 이런 경우에 즉각적인 쓰기를 요청하는 메소드가 있습니다만 그 효과가 100% 확실히….라고 장담할 수는 없다고 알고있습니다.
둘째, JVM 내부에서 사용하는 바이트 순서는 운영체제의 바이트 순서와 틀릴 수 있습니다.
JVM에서 사용하는 바이트 오더는 네트워크와 마찬가지로 빅 인디안 입니다. 파일에서 같은 지점에서 같은 4바이트를 읽어들였다고 하더라도 C로 작성한 네이티브 프로세서와 자바 어플레이케이션에서 나타나는 INT 값은 다를 수가 있습니다.
마지막으로 C에서 멤버값을 사용하는 방식은 ‘포인터’입니다. 참조를 통해서 접근하고 싶다면 참조값을 JVM에서 어떤 방식을 써서든 제공해야하는데… 아시다시피 Shared Memory는 GC의 대상이 아닙니다. 즉, 참조값을 만든다고 하더라도 JVM 입장에서는 관리가 불가능한 애물단지인 셈이죠. 겉보기에 조금 편한 방법일 뿐, 결국 JVM에게 ‘내가 원하는 장소의 메모리 접근을 허용해 달라’는 것인데 마찬가지로 원칙적으로 허용되지 않는 일입니다.
그래서 어떻게 하란말이냐?
이럴 때 나오는 ‘전가의 보도’, JNI 나 JNA 밖에 없습니다. -_-;; 메모리맵 파일을 이용한 여러가지 편법이 있겠지만, 정말로 ‘Shared Memory’를 사용하시고 싶으시다면 답은 오로지 하나. 자바 프로세스(JVM)과 C 프로세스를 연결하는 별도의 중간 C 프로세스를 DLL 형태로 만들어서 loadLibrary()를 사용해서 함수를 호출하는 겁니다. 물론 다소 오버헤드가 있다고 알고 있지만 정말 크리티컬한 애플리케이션이 아니면 상관없다고 들었습니다.
기타 참고 :
http://www.velocityreviews.com/forums/t141702-shared-memory-in-java.html
http://forums.sun.com/thread.jspa?messageID=2699137
http://www.koders.com/java/fidE1510F023E541D2578505E190C4162A777AFD5B4.aspx?s=file%3Asemap*.java
http://www.codeproject.com/KB/java/sharedmem_jni.aspx