线程“main”中的异常java.lang.UnsatisfiedLinkError从Java调用C ++ DLL方法时

时间:2017-01-25 08:36:23

标签: java c++ dll java-native-interface native

我在调用FindElements类的方法initizlize()时,在线程“main”java.lang.UnsatisfiedLinkError:FindElements.initialize()V中遇到异常。请查看附带的详细信息。 据我所知,可以加载DLL,但是在调用方法时会抛出异常。我已多次手动检查方法签名以确保它们是正确的。

"C:\Program Files\Java\jdk1.8.0_73\bin\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.0\bin" -Dfile.encoding=UTF-8 -classpath "C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\target\classes;C:\Program Files\Java\jdk1.8.0_73\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\rt.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_73\jre\lib\ext\zipfs.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\jna-4.0.0.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\jawin-stubs.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\jawin.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\JNativeHook.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\commons-configuration-1.6.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\jfxrt.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\commons-lang-2.5.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\commons-logging-1.1.1.jar;C:\Users\Mike\Desktop\Summer_Research_2016\Gaze UI Automation\lib\commons-collections-3.2.1.jar;C:\Users\Mike\.m2\repository\com\github\mmarquee\ui-automation\0.3.10\ui-automation-0.3.10.jar;C:\Users\Mike\.m2\repository\net\java\dev\jna\jna\4.3.0\jna-4.3.0.jar;C:\Users\Mike\.m2\repository\net\java\dev\jna\jna-platform\4.3.0\jna-platform-4.3.0.jar;C:\Users\Mike\.m2\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;C:\Users\Mike\.m2\repository\org\hamcrest\hamcrest-all\1.3\hamcrest-all-1.3.jar;C:\Users\Mike\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\Mike\.m2\repository\org\mockito\mockito-core\2.0.28-beta\mockito-core-2.0.28-beta.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.0\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain testBetaUIFrame
Exception in thread "main" java.lang.UnsatisfiedLinkError: FindElements.initialize()V
    at FindElements.initialize(Native Method)
    at testBetaUIFrame.main(testBetaUIFrame.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Process finished with exit code 1

调用JNI的Java类:

LibraryConfiguration类将指定的文件夹添加到库路径。

public class FindElements {
    public native void initialize();
    public native String[] getElements(int type);
    public native void invokeElement(int index, int type);
    public native void uninitialize();

    static {
        try {
            LibraryConfiguration.addLibraryPath(
                    LibraryConfiguration.changeFileSeparator("\\libs"));
            System.loadLibrary("FindElements");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

FindElements.cpp

#include <windows.h>
#include "stdafx.h"
#include <stdio.h>
#include "jni.h"
#include "FindElements.h"
#include <string>
#include <math.h>
#include <vector>
#include "UIAutomationClient.h"
#include "UIAutomation.h"

#pragma comment(lib,"Ole64.lib")
#pragma comment(lib,"User64.lib")
#pragma comment(lib,"OleAut64.lib")
using namespace std;
int BUTTON = 0;
int SPLITBUTTON = 1;
int HYPERLINK = 2;
int TREEITEM = 3;
int TABITEM = 4;
int MENUITEM = 5;
int EDIT = 6;
int LISTITEM = 7;
IUIAutomation *g_pAutomation;
IUIAutomationElement *parent = NULL;

IUIAutomationElementArray *cbuttons = NULL;//0
IUIAutomationElementArray *cSplitButtons = NULL;//1
IUIAutomationElementArray *cHyperLinks = NULL;//2
IUIAutomationElementArray *cTreeItems = NULL;//3
IUIAutomationElementArray *cTabItems = NULL;//4
IUIAutomationElementArray *cMenuItems = NULL;//5
IUIAutomationElementArray *cEdit = NULL;//6
IUIAutomationElementArray *cListItem = NULL;//7
unsigned int DISTANCE = 75;
string& BstrToStdString(const BSTR bstr, string& dst, int cp = CP_UTF8)
{
......
}
// conversion with temp.
string BstrToStdString(BSTR bstr, int cp = CP_UTF8)
{
    string str;
    BstrToStdString(bstr, str, cp);
    return str;
}
extern "C" {
    IUIAutomationElementArray* GetElements(IUIAutomationElement* pParent, VARIANT varProp)
    {
        if (pParent == NULL)
        {
            return NULL;
        }
        IUIAutomationCondition* pCondition = NULL;
        IUIAutomationCondition* pEnabledCondition = NULL;
        IUIAutomationCondition* pCombinedCondition = NULL;
        IUIAutomationElementArray* pFound = NULL;
        g_pAutomation->CreatePropertyCondition(UIA_ControlTypePropertyId, varProp, &pCondition);
        if (pCondition == NULL)
            goto cleanup;

        // Create a property condition for the enabled property.
        varProp.vt = VT_BOOL;
        varProp.boolVal = VARIANT_TRUE;
        g_pAutomation->CreatePropertyCondition(UIA_IsEnabledPropertyId, varProp, &pEnabledCondition);
        if (pEnabledCondition == NULL)
            goto cleanup;

        // Combine the conditions.
        g_pAutomation->CreateAndCondition(pCondition, pEnabledCondition, &pCombinedCondition);
        if (pCombinedCondition == NULL)
            goto cleanup;

        // Find the matching elements. Note that if the scope is changed to TreeScope_Descendants, 
        // system buttons on the caption bar will be found as well.
        pParent->FindAll(TreeScope_Descendants, pCombinedCondition, &pFound);

    cleanup:
        if (pCondition != NULL)
            pCondition->Release();

......

        return pFound;
    }
    IUIAutomationElement* GetContainingWindow(IUIAutomationElement* pChild)
    {

        if (pChild == NULL)
            return NULL;

        IUIAutomationElement* pDesktop = NULL;
        HRESULT hr = g_pAutomation->GetRootElement(&pDesktop);
        if (FAILED(hr))
            return NULL;

        BOOL same;
        g_pAutomation->CompareElements(pChild, pDesktop, &same);
        if (same)
        {
            pDesktop->Release();
            return NULL; // No parent, so return NULL.
        }

        IUIAutomationElement* pParent = NULL;
        IUIAutomationElement* pNode = pChild;

        // Create the treewalker.
        IUIAutomationTreeWalker* pWalker = NULL;
        g_pAutomation->get_ControlViewWalker(&pWalker);
        if (pWalker == NULL)
            goto cleanup;

        // Walk up the tree.
        while (TRUE)
        {
            hr = pWalker->GetParentElement(pNode, &pParent);
            if (FAILED(hr) || pParent == NULL)
            {
                break;
            }
            g_pAutomation->CompareElements(pParent, pDesktop, &same);
            if (same)
            {
                pDesktop->Release();
                pParent->Release();
                pWalker->Release();
                // Reached desktop, so return next element below it.
                return pNode;
            }
            if (pNode != pChild) // Do not release the in-param.
                pNode->Release();
            pNode = pParent;
        }

    cleanup:
        if ((pNode != NULL) && (pNode != pChild))
            pNode->Release();

......

        return NULL;
    }
    JNIEXPORT void JNICALL Java_FindElements_initialize(JNIEnv *env, jobject obj)
    {
        CoInitializeEx(NULL, COINIT_MULTITHREADED);
        HRESULT hr = CoCreateInstance(__uuidof(CUIAutomation), NULL,
            CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation),
            (void**)&g_pAutomation);
        POINT pt;
        GetPhysicalCursorPos(&pt);

        IUIAutomationElement *pAtMouse;
        hr = g_pAutomation->ElementFromPoint(pt, &pAtMouse);

        parent = GetContainingWindow(pAtMouse);

        hr = parent->SetFocus();

    }
    JNIEXPORT jobjectArray JNICALL Java_FindElements_getElements(JNIEnv *env, jobject obj, jint type)
    {
        jobjectArray objArray;
        vector<string> name, index;
        vector<string> left, top, right, bottom;
        int k = 0;
        string str, str1, str2;
        HRESULT hr;
        if (type == BUTTON)
        {......}
        objArray = (jobjectArray)env->NewObjectArray(k,
            env->FindClass("java/lang/String"),
            env->NewStringUTF(""));
        for (int i = 0; i < k; i++)
        {
            string st = index.at(i) + "l" + left.at(i) + "t" + top.at(i) + "r" + right.at(i) + "b" + bottom.at(i) + " " + name.at(i);
            const char * n = st.c_str();
            env->SetObjectArrayElement(objArray, i, env->NewStringUTF(n));
        }
        return objArray;
    }

    JNIEXPORT void JNICALL Java_FindElements_invokeElement(JNIEnv *, jobject, jint index, jint type)
    {
        IUIAutomationElement *cele = NULL;//used to find the invoke pattern
        IUIAutomationInvokePattern *pPattern = NULL;
        HRESULT hr;
        if (type == BUTTON)
        {......     }
        cele = NULL;
    }

    JNIEXPORT void JNICALL Java_FindElements_uninitialize(JNIEnv *env, jobject obj)
    {
        if (cbuttons != NULL)
        {......     }

    }
}

FindElements.h

   /* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class FindElements */

#ifndef _Included_FindElements
#define _Included_FindElements
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     FindElements
 * Method:    initialize
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_FindElements_initialize
  (JNIEnv *, jobject);

/*
 * Class:     FindElements
 * Method:    getElements
 * Signature: (I)[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_FindElements_getElements
  (JNIEnv *, jobject, jint);

/*
 * Class:     FindElements
 * Method:    invokeElement
 * Signature: (II)V
 */
JNIEXPORT void JNICALL Java_FindElements_invokeElement
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     FindElements
 * Method:    uninitialize
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_FindElements_uninitialize
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

来自javah的FindElements.h:

(更新)仍然是同样的错误。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class FindElements */

#ifndef _Included_FindElements
#define _Included_FindElements
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     FindElements
 * Method:    initialize
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_FindElements_initialize
  (JNIEnv *, jobject);

/*
 * Class:     FindElements
 * Method:    getElements
 * Signature: (I)[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_FindElements_getElements
  (JNIEnv *, jobject, jint);

/*
 * Class:     FindElements
 * Method:    invokeElement
 * Signature: (II)V
 */
JNIEXPORT void JNICALL Java_FindElements_invokeElement
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     FindElements
 * Method:    uninitialize
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_FindElements_uninitialize
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

我在Visual Studio中的属性设置中添加了必要DLL的路径。

其他目录C ++ General

enter image description here

其他目录链接器

enter image description here

有人可以提出任何建议吗?

1 个答案:

答案 0 :(得分:0)

看起来你的代码中有一些奇怪的东西。

您的标题有以下内容:

JNIEXPORT jboolean JNICALL Java_EyeXJavaWrapper_initialize
  (JNIEnv *, jobject);

在你的代码(cpp)中你有

JNIEXPORT void JNICALL Java_FindElements_initialize(JNIEnv *env, jobject obj)

您是否使用javah生成头文件?

javah -jni -cp where_your_class_files_are FindElements

我还建议将FindElements放在包中。你可以在这里找到关于JNI的非常基础的教程:http://jnicookbook.owsiak.org/recipe-No-001/