FileDescriptor의 native 메소드가 어떻게 리눅스와 윈도우에 포팅되었는지 확인한다.
1. 자바 소스
java.io.FileDescriptor.java
package java.io; public final class FileDescriptor { private long handle; ….. public native void sync() throws SyncFailedException; /* This routine initializes JNI field offsets for the class */ private static native long set(int d); } |
2, native 소스
jdk 6u 22 소스 - FileDescriptor_md.c
/* #include "jni.h" #include "java_io_FileDescriptor.h" /*******************************************************************/ /* field id for jint 'fd' in java.io.FileDescriptor */ /* field id for jlong 'handle' in java.io.FileDescriptor */ /************************************************************** JNIEXPORT void JNICALL JNIEXPORT jlong JNICALL /************************************************************** JNIEXPORT void JNICALL |
3. 윈도우 구현
윈도우에서는 SET_HANDLE과 IO_Sync을 다음과 같이 정의하였다.
src/windows/native/java/io/io_util_md.h 파일
SET_HANDLE 매크로에서 input,output,error에 값에 대한 GetStdHandle 함수를 사용한다. (http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231(v=vs.85).aspx
JNIEXPORT int handleSync(jlong fd); /* #define IO_Sync handleSync |
src/windows/native/java/io/io_util_md.c 파일
결국 자바의 sync는 윈도우의 FlushFileBuffers(핸들값) 함수를 이용한다. (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364439(v=vs.85).aspx)
JNIEXPORT int HANDLE handle = (HANDLE)fd; if (!FlushFileBuffers(handle)) { |
4. 리눅스 구현
src/sloaris/native/java/io/FileDescriptor_md.c
/* field id for jint 'fd' in java.io.FileDescriptor */ /************************************************************** JNIEXPORT void JNICALL /************************************************************** JNIEXPORT void JNICALL |
src/solaris/native/java/io/io_util_md.h 파일
set_handle은 깔끔히 무시해준다.
/* #define IO_Sync JVM_Sync /* |
hotspot/src/share/vm/prims/jvm.cpp 파일
JVM_LEAF(jint, JVM_Sync(jint fd)) JVMWrapper2("JVM_Sync (0x%x)", fd); //%note jvm_r6 return hpi::fsync(fd); JVM_END |
JVMWrapper2 매크로는 jvm.cpp에 정의되어 있다. 특별한 일은 하지 않는다.
#define JVMWrapper2(arg1, arg2) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2) #define JVMCountWrapper(arg) \ class JVMTraceWrapper : public StackObj { |
hpi::fsync() 함수의 원형은 hotspot/src/share/vm/runtime/hpi.hpp, hotspot/src/share/vm/runtime/hpi.h 에 있다.
hotspot/src/share/vm/runtime/hpi.h
typedef struct { |
hotspot/src/share/vm/runtime/hpi.cpp
// class hpi : AllStatic { static HPI_FileInterface* _file; static inline int fsync(int fd); HPIDECL(fsync, "fsync", _file, Sync, int, "%d", } |
hpi.c
static HPI_FileInterface hpi_file_interface = { sysNativePath, sysFileType, sysOpen, sysClose, sysSeek, sysSetLength, sysSync, sysAvailable, sysRead, sysWrite, sysFileSizeFD }; |
hpi_impl.h
int sysSync(int fd); |
sys_api_td.c
int sysSync(int fd) { /* * XXX: Is fsync() interruptible by the interrupt method? * Is so, add the TSD, sigsetjmp()/longjmp() code here. * * This probably shouldn't be throwing an error and should * be a macro. */ int ret; if ((ret = fsync(fd)) == -1) { } return ret; } |
리눅스의 sync 호출은 간단히 리눅스의 fsync 함수를 호출하는 효과와 동일하다.
마치며.
재미있는 것은 파일(file), 소켓(socket), 모니터(lock) 모두 jvm.cpp를 거쳐 hpi.hpp 로 내려오게 된다. 파일의 경우는 IO lock/unlock의 개념도 있고. 공부할 내용이 풍부하다..
이제 시간되는 대로 jvm 내용을 찾아 들어가면 될 것 같다.
'java core' 카테고리의 다른 글
SofreReference, WeakReference, PhantomReference (0) | 2012.03.29 |
---|---|
String의 codePointCount 메서드 (0) | 2012.03.13 |
java 7 은 glic 2.4 이상의 linux에서 동작 (0) | 2012.02.16 |
Oracle에서 jdk 7 부터는 G1를 디폴트로 사용한다고 했었는데.. 적용되고 있지 않다. (0) | 2012.02.10 |
JDK 버그-classloader가 array 타입의 클래스 로딩시 ClassNotFoundException발생 (2012.2.현재) (0) | 2012.02.10 |