2013-05-10 78 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