载入JNI Dll [英] Loading JNI Dll

查看:92
本文介绍了载入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);
}

然后我使用javah生成jni文件:

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加载,我就会像这样调用一个函数:

长句柄= 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

有什么想法我做错了吗?

我建议您编码并构建具有Unicode支持的JNI DLL,并使用GetStringChars创建UTF-16字符串以传递给CreateFileMapping. CreateFileMapping的任何版本都不能使用GetStringUTFChars返回的UTF-8字符串.如果必须使用ANSI版本,则在调用CreateFileMapping之前,请执行从Unicode到ANSI字符串的正确转换.

IMO,GetStringUTFChars应该命名为GetStringUTF8Chars.

别忘了将GetStringCharsReleaseStringChars配对.

I have a file written as follows:

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);
}

Then I generate the jni file using 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))));
}

But as soon as the DLL loads and I call a function like so:

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

it prints:

run:

#
# 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

Any ideas what I did wrong?

解决方案

I suggest that you code and build your JNI DLL with Unicode support, and use GetStringChars to create UTF-16 strings to pass to CreateFileMapping. No version of CreateFileMapping takes the UTF-8 strings that are returned by GetStringUTFChars. If you must use the ANSI version then do a proper conversion from Unicode to ANSI strings before calling CreateFileMapping.

IMO, GetStringUTFChars should be named GetStringUTF8Chars.

Don't forget to pair GetStringChars with ReleaseStringChars.

这篇关于载入JNI Dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆