寻 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
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() ); } }
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 ); } } } }
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; }}
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(); }
/* 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
#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);}