2013-05-10 74 views
1

我有一個文件寫成如下:加載JNI的Dll

package JNI; 

public class Natives { 

    public static final int PAGE_READONLY = 0x02; 
    public static final int PAGE_READWRITE = 0x04; 
    public static final int PAGE_WRITECOPY = 0x08; 
    public static final int FILE_MAP_COPY = 0x0001; 
    public static final int FILE_MAP_WRITE = 0x0002; 
    public static final int FILE_MAP_READ = 0x0004; 

    public static native long createFileMapping(long hFile, int lpAttributes, int dwMaximumSizeHigh, int dwMaximumSizeLow, String lpName); 

    public static native long openFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName); 

    public static native long mapViewOfFile(long hFileMap, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap); 

    public static native long unmapViewOfFile(long hFileMap); 

    public static native long closeHandle(long hFile); 
} 

然後我用生成JNI文件JAVAH:

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_createFileMapping(JNIEnv *env, jclass, jlong hFile, jint lpProtect, jint dwMaximumSizeHigh, jint dwMaximumSizeLow, jstring lpName) 
{ 
    HANDLE hFileMap = nullptr; 
    LPCSTR Name = env->GetStringUTFChars(lpName, nullptr); 

    if ((hFileMap = CreateFileMapping(hFile == -1 ? INVALID_HANDLE_VALUE : reinterpret_cast<HANDLE>(hFile), nullptr, lpProtect, dwMaximumSizeHigh, dwMaximumSizeLow, Name)) != nullptr) 
    { 
     if (errno == ERROR_ALREADY_EXISTS) 
     { 
      CloseHandle(hFileMap); 
     } 
    } 

    env->ReleaseStringUTFChars(lpName, Name); 
    return reinterpret_cast<jlong>(hFileMap); 
} 

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_openFileMapping(JNIEnv *env, jclass, jint dwDesiredAccess, jboolean bInheritHandle, jstring lpName) 
{ 
    LPCSTR Name = env->GetStringUTFChars(lpName, nullptr); 
    HANDLE hFileMap = OpenFileMapping(dwDesiredAccess, static_cast<bool>(bInheritHandle), Name); 
    env->ReleaseStringUTFChars(lpName, Name); 
    return reinterpret_cast<jlong>(hFileMap); 
} 

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_mapViewOfFile(JNIEnv *, jclass, jlong hFileMap, jint dwDesiredAccess, jint dwFileOffsetHigh, jint dwFileOffsetLow, jint dwNumberOfBytesToMap) 
{ 
    void* pData = MapViewOfFile(reinterpret_cast<HANDLE>(hFileMap), dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap); 
    return reinterpret_cast<jlong>(pData); 
} 

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_unmapViewOfFile(JNIEnv *, jclass, jlong hFileMap) 
{ 
    return reinterpret_cast<jboolean>(static_cast<uint8_t>(UnmapViewOfFile(reinterpret_cast<void*>(hFileMap)))); 
} 

extern "C" JNIEXPORT jlong JNICALL Java_JNI_Natives_closeHandle(JNIEnv *, jclass, jlong hFile) 
{ 
    return reinterpret_cast<jboolean>(static_cast<uint8_t>(CloseHandle(reinterpret_cast<HANDLE>(hFile)))); 
} 

但只要加載DLL和我打電話的功能等所以:

long Handle = Natives.createFileMapping(-1,Natives.FILE_MAP_READ | Natives.FILE_MAP_WRITE,500,0,「NativeDLL」); debug(Handle);

它打印:

運行:

# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000061288f69, pid=4692, tid=844 
# 
# JRE version: 7.0_21-b11 
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.21-b01 mixed mode windows-amd64 compressed oops) 
# Problematic frame: 
# V [jvm.dll+0x38f69] 
# 
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows 
# 
# An error report file with more information is saved as: 
# C:\Users\Brandon\Documents\NetBeansProjects\Smart\hs_err_pid4692.log 
# 
# If you would like to submit a bug report, please visit: 
# http://bugreport.sun.com/bugreport/crash.jsp 
# 
Java Result: 1 

任何想法,我做錯了什麼?

回答

1

我建議你編碼和建立你的JNI DLL的Unicode支持,並使用GetStringChars來創建UTF-16字符串傳遞到CreateFileMapping。沒有版本的CreateFileMapping需要由GetStringUTFChars返回的UTF-8字符串。如果您必須使用ANSI版本,請在調用CreateFileMapping之前從Unicode到ANSI字符串進行適當的轉換。

IMO,GetStringUTFChars應該被命名爲GetStringUTF8Chars

不要忘記配對GetStringCharsReleaseStringChars

+0

:S GetStringUTFChars返回一個const char *,CreateFileMapping將其作爲最後一個參數。我喜歡你的答案,但我仍然遇到與unicode轉換有關的問題。 – Brandon 2013-05-10 19:41:01

+0

@CantChooseUsernames每個字符串都是來自特定字符集的編碼字符序列。 'CreateFileMapping'是'CreateFileMappingA'或'CreateFileMappingW'的別名。第一個需要使用當前ANSI代碼頁編碼的字符串。第二個需要使用UTF-16LE編碼的字符串。所以,我再說一次,_no版本的'CreateFileMapping'接受'GetStringUTFChars'_返回的UTF-8字符串。指針類型並不重要。它僅表示編碼的最小元素,但沒有提及編碼或字符集。 – 2013-07-23 23:33:48

+0

我使用上面相同的代碼解決了它。我只需要改變調用約定並使用.def文件導出。代碼也可以工作。 – Brandon 2013-07-24 17:20:45

1

這可能是一個權限問題。

您可以考慮使用Java Native Access/JNA具有更試過&健壯的實現原生平臺API的比你都不可能單獨實現(取決於課程的經驗)。它由Netbeans IDE等人使用。

具體參見com.sun.jna.platform.win32 Kernel32 Interface其中包含這些方法。

+0

:o從未在我的生活中想過這件事,但只要我將它移動到C:/目錄並編譯完成,它就擁有了它所需的所有權限並能夠正常工作。尷尬。 – Brandon 2013-05-10 19:41:44