读书人

寻 JNI高手帮忙解决一个有关问题万分

发布时间: 2012-09-02 21:00:34 作者: rapoo

寻 JNI高手帮忙解决一个问题,万分感谢!
JNI 达人,我改写了一个全局监听的 java调用 dll的代码,可是一运行就 JVM crash.

请达人帮我看看是什么原因,非常感谢!


运行环境:

OS: Windows XP Build 2600 Service Pack 3

CPU:total 2 (2 cores per cpu, 1 threads per core) family 6 model 23 stepping 10, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1

Memory: 4k page, physical 2091204k(875764k free), swap 4029236k(2644760k free)

vm_info: Java HotSpot(TM) Client VM (20.4-b02) for windows-x86 JRE (1.6.0_29-b11), built on Oct 3 2011 01:01:08 by "java_re" with MS VC++ 7.1 (VS2003)


Example.java

Java code
package jni;public class Example  implements KeyboardEventListener {    static GlobalEventListener gl;    public static void main(String[] args) throws Exception      {        Example inst = new Example();        gl = new GlobalEventListener();          gl.addKeyboardEventListener(inst);    }                public void GlobalKeyPressed( KeyboardEvent event )    {                System.out.println( "Key Pressed: " + event.getVirtualKeyCode() );    }    public void GlobalKeyReleased( KeyboardEvent event )    {        System.out.println( "Key Released: " + event.getVirtualKeyCode() );    }    }



GlobalEventListener.java
Java code
package jni;public class GlobalEventListener{    PoolHook pt;    public GlobalEventListener()    {        pt = new PoolHook(this);        pt.start();                }     protected javax.swing.event.EventListenerList listenerList = new javax.swing.event.EventListenerList();         public void addKeyboardEventListener(KeyboardEventListener listener)    {        listenerList.add( KeyboardEventListener.class, listener );    }     public void removeKeyboardEventListener(KeyboardEventListener listener)    {        listenerList.remove( KeyboardEventListener.class, listener );    }            void keyPressed(KeyboardEvent event)    {        Object[] listeners = listenerList.getListenerList();        for ( int i = 0; i < listeners.length; i += 2 )        {            if ( listeners[ i ] == KeyboardEventListener.class )            {                ( (KeyboardEventListener)listeners[i + 1] ).GlobalKeyPressed( event );            }        }    }     void keyReleased(KeyboardEvent event)    {        Object[] listeners = listenerList.getListenerList();        for ( int i = 0; i < listeners.length; i += 2 )        {            if ( listeners[ i ] == KeyboardEventListener.class )            {                ( (KeyboardEventListener)listeners[i + 1] ).GlobalKeyReleased( event );            }        }    }        } 



KeyboardEventListener.java
Java code
package jni;import java.util.*; public interface KeyboardEventListener extends EventListener{    public void GlobalKeyPressed( KeyboardEvent event );    public void GlobalKeyReleased( KeyboardEvent event );}class KeyboardEvent extends EventObject{    private static final long serialVersionUID = 2341653211621224652L;    boolean ts, ap, ek;    int vk;     public KeyboardEvent( Object source, boolean ts, int vk, boolean ap, boolean ek )    {        super(source);        this.ts = ts;        this.vk = vk;        this.ap = ap;        this.ek = ek;    }     public boolean getTransitionState()    {        return ts;    }     public long getVirtualKeyCode()    {        return vk;    }     public boolean isAltPressed()    {        return ap;    }     public boolean isExtendedKey()    {        return ek;    }     public boolean equals( KeyboardEvent event )    {        if( event.getVirtualKeyCode() == vk )        {            if( event.isExtendedKey() == ek )            {                if( event.isAltPressed() == ap )                {                    return true;                }            }        }        return false;    }} 




SysHook.java
Java code
package jni;class PoolHook extends Thread{    SysHook hook;    GlobalEventListener g_gl;    PoolHook(GlobalEventListener gl)    {        g_gl = gl;    }            public void run()     {        hook = new SysHook();        hook.registerHook(g_gl);    }    }class SysHook{        static     {        System.loadLibrary("SysHook");    }        void processKey(  boolean ts  ,int vk, GlobalEventListener gl)     {        KeyboardEvent event = new KeyboardEvent( this, ts, vk,false, false );        if(ts == true)            gl.keyPressed(event);        else if(ts == false)            gl.keyReleased(event);    }        void mouseMoved(int cord_x, int cord_y, GlobalEventListener gl)     {        //MouseEvent event = new MouseEvent( this, cord_x, cord_y);        //gl.mouseMoved(event);    }    native void registerHook(GlobalEventListener gl);    native void unRegisterHook();    }



jni_SysHook.h
C/C++ code
/* DO NOT EDIT THIS FILE - it is machine generated */#include "jni.h"/* Header for class jni_SysHook */#ifndef _Included_jni_SysHook#define _Included_jni_SysHook#ifdef __cplusplusextern "C" {#endif/* * Class:     jni_SysHook * Method:    registerHook * Signature: (Ljni/GlobalEventListener;)V */JNIEXPORT void JNICALL Java_jni_SysHook_registerHook  (JNIEnv *, jobject, jobject);/* * Class:     jni_SysHook * Method:    unRegisterHook * Signature: ()V */JNIEXPORT void JNICALL Java_jni_SysHook_unRegisterHook  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif



SysHook.cpp
C/C++ code
#include <windows.h>#include <WinUser.h>#include "SysHook.h"#include "jni_SysHook.h"#include "jni.h"#ifndef WINVER#define WINVER 0x0500#endif#ifndef _WIN32_WINNT#define _WIN32_WINNT 0x0500#endif#if (_WIN32_WINNT >= 0x0400)#define WH_KEYBOARD_LL 13#define WH_MOUSE_LL 14#endif // (_WIN32_WINNT >= 0x0400)typedef   struct   tagKBDLLHOOKSTRUCT   {          DWORD   vkCode;             //   virtual   key   code          DWORD   scanCode;         //   scan   code          DWORD   flags;               //   flags          DWORD   time;                 //   time   stamp   for   this   message          DWORD   dwExtraInfo;   //   extra   info   from   the   driver   or   keybd_event  }KBDLLHOOKSTRUCT,   FAR   *LPKBDLLHOOKSTRUCT,   *PKBDLLHOOKSTRUCT;HINSTANCE hInst = NULL;JavaVM * jvm = NULL;jobject hookObj_kb = NULL;jobject hookObj_ms = NULL;jobject g_kl = NULL;jmethodID processKeyID_kb = NULL;jmethodID processKeyID_ms = NULL;DWORD hookThreadId = 0;LONG g_mouseLocX = -1;    // x-location of mouse positionLONG g_mouseLocY = -1;    // y-location of mouse positionextern "C"BOOL APIENTRY DllMain(HINSTANCE _hInst, DWORD reason, LPVOID reserved){    switch (reason)    {    case DLL_PROCESS_ATTACH:        printf("C++: DllMain - DLL_PROCESS_ATTACH.\n");        hInst = _hInst;        break;    default:        break;    }        return TRUE;}LRESULT CALLBACK MouseTracker(int nCode, WPARAM wParam, LPARAM lParam){    JNIEnv * env;    KBDLLHOOKSTRUCT * p = (KBDLLHOOKSTRUCT *)lParam;        if (jvm->AttachCurrentThread((void **)&env, NULL) >= 0)    {                if (nCode==HC_ACTION)        {            MOUSEHOOKSTRUCT* pStruct = (MOUSEHOOKSTRUCT*)lParam;            if (pStruct->pt.x != g_mouseLocX || pStruct->pt.y != g_mouseLocY)            {                env->CallVoidMethod(hookObj_ms, processKeyID_ms, (jint)pStruct->pt.x,(jint)pStruct->pt.y, g_kl);                g_mouseLocX = pStruct->pt.x;                g_mouseLocY = pStruct->pt.y;            }                    }            }    else    {        printf("C++: LowLevelKeyboardProc - Error on the attach current thread.\n");    }        return CallNextHookEx(NULL, nCode, wParam, lParam);}LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam){    JNIEnv * env;    KBDLLHOOKSTRUCT * p = (KBDLLHOOKSTRUCT *)lParam;        if(jvm->AttachCurrentThread((void **)&env, NULL) >= 0)    {        switch (wParam)        {        case WM_KEYDOWN:        case WM_SYSKEYDOWN:            env->CallVoidMethod(hookObj_kb, processKeyID_kb, (jboolean)TRUE, p->vkCode,g_kl);            break;        case WM_KEYUP:        case WM_SYSKEYUP:            env->CallVoidMethod(hookObj_kb, processKeyID_kb, (jboolean)FALSE, p->vkCode,g_kl);            break;        default:            break;        }    }    else    {        printf("C++: LowLevelKeyboardProc - Error on the attach current thread.\n");    }        return CallNextHookEx(NULL, nCode, wParam, lParam);}void MsgLoop(){    MSG message;    while (GetMessage(&message, NULL, 0, 0))    {        TranslateMessage(&message);        DispatchMessage(&message);    }}JNIEXPORT void JNICALL Java_jni_SysHook_registerHook(JNIEnv * env, jobject obj,jobject kl){    HHOOK hookHandle_ms = SetWindowsHookEx(WH_MOUSE_LL, MouseTracker, hInst, 0);    HHOOK hookHandle_kb = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInst, 0);        g_kl = kl;        if (hookHandle_ms == NULL)    {        printf("C++: Java_SysHook_registerKeyHook - Hook failed!\n");        return;    }    else    {        printf("C++: Java_SysHook_registerKeyHook - Hook successful\n");    }        if (hookHandle_kb == NULL)    {        printf("C++: Java_SysHook_registerKeyHook - Hook failed!\n");        return;    }    else    {        printf("C++: Java_SysHook_registerKeyHook - Hook successful\n");    }        hookObj_kb = env->NewGlobalRef(obj);    jclass cls_kb = env->GetObjectClass(hookObj_kb);    processKeyID_kb = env->GetMethodID(cls_kb, "processKey", "(ZILGlobalEventListener;)V");        hookObj_ms = env->NewGlobalRef(obj);    jclass cls_ms = env->GetObjectClass(hookObj_ms);    processKeyID_ms = env->GetMethodID(cls_ms, "mouseMoved", "(IILGlobalEventListener;)V");        env->GetJavaVM(&jvm);    hookThreadId = GetCurrentThreadId();        MsgLoop();        if (!UnhookWindowsHookEx(hookHandle_kb))    {        printf("C++: Java_SysHook_registerKeyHook - Unhook failed\n");    }    else    {        printf("C++: Java_SysHook_registerKeyHook - Unhook successful\n");    }        if (!UnhookWindowsHookEx(hookHandle_ms))    {        printf("C++: Java_SysHook_registerKeyHook - Unhook failed\n");    }    else    {        printf("C++: Java_SysHook_registerKeyHook - Unhook successful\n");    }}JNIEXPORT void JNICALL Java_jni_SysHook_unRegisterHook(JNIEnv *env, jobject object){    if (hookThreadId == 0)        return;        printf("C++: Java_SysHook_unRegisterKeyHook - call PostThreadMessage.\n");    PostThreadMessage(hookThreadId, WM_QUIT, 0, 0L);} 



[解决办法]
问题我想应该找到了:
这两行:
processKeyID_kb = env->GetMethodID(cls_kb, "processKey", "(ZILGlobalEventListener;)V");

processKeyID_ms = env->GetMethodID(cls_ms, "mouseMoved", "(IILGlobalEventListener;)V");

得到的processKeyID_kb和processKeyID_ms应该为NULL,你可以打印看看,之后调用CallVoidMethod肯定会空指针.
(ZILGlobalEventListener;)V应该是全限定性名称:(ZILjni/GlobalEventListener;)V

(IILGlobalEventListener;)V同样的应该改为(IILjni/GlobalEventListener;)V

你试试看

读书人网 >J2SE开发

热点推荐