JNI方法退出时的java.lang.StackOverflowError

时间:2018-02-14 12:47:13

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

我使用Windows EvtSubscribe(推送)来获取事件并将其发送到java进行处理。从方法Java_evetsubscribepush返回时,我在java中接收 java.lang.StackOverflowError 。这是我的示例代码。无论它运行几秒钟还是几个小时 java.lang.StackOverflowError 仅在代码退出时发生,而不是在发送事件的java用法之间。我有什么遗失的吗?

JNIEXPORT jobject JNICALL Java_evetsubscribepush(JNIEnv *env, jobject obj){
    wprintf( L"\n Java_evetsubscribepush starts");
    CoInitialize(NULL);
    DWORD res = ERROR_SUCCESS;
    EventSubscribeLog * handler = new EventSubscribeLog();
    res = handler->EventSubscribePush ( handler ,env);
    CoUninitialize();
    wprintf( L"\n Java_evetsubscribepush ends" );
    return NULL;
}

DWORD EventSubscribeLog::EventSubscribePush ( EventSubscribeLog * handler , JNIEnv *javaEnv)
{
    DWORD status = ERROR_SUCCESS;
    LPWSTR Path = L"Security";
    LPWSTR Query =  L"<QueryList>" \
                    L"  <Query Id='0' Path='Security'>" \
                    L"    <Select Path='Security'>*</Select>" \
                    L"  </Query>" \
                    L"</QueryList>";
    EVT_HANDLE hSubscription = NULL;
    EVT_HANDLE sessionHndl = OpenRemoteSession ();
    if (sessionHndl == NULL) {
        log ( javaEnv, L"\n EvtSubscribe open remote session failed in %lu", status );
        goto exit;
    }

    DWORD callBACKstatus = ERROR_SUCCESS;
    USER_CONTEXT UserContext;
    UserContext.handler = handler;
    UserContext.callBACKstatus = &callBACKstatus;
    UserContext.env = javaEnv;

    hSubscription = EvtSubscribe ( sessionHndl, NULL, Path, Query, NULL, &UserContext,
        (EVT_SUBSCRIBE_CALLBACK) EventSubscribeLog::SubscriptionCallback, EvtSubscribeToFutureEvents );

    if (NULL == hSubscription) {
        status = GetLastError ( );
        log ( javaEnv, L"\n EvtSubscribe failed  %lu. ", status );
        goto exit;
    }
    while (true) {
        if (ERROR_SUCCESS != callBACKstatus) {
            status = callBACKstatus;
            log ( javaEnv, L"\n EvtSubscribe call Back failed with error code %lu. ", status );
            goto exit;
        }
        Sleep ( 5000 );
    }
    log ( javaEnv, L"\n EvtSubscribe PUSH ends. " );
exit:
    if (hSubscription) {
        EvtClose ( hSubscription );
    }
    if (sessionHndl) {
        EvtClose ( sessionHndl );
    }
    if (Query != NULL) {
        free ( Query );
        Query = NULL;
    }
    return status;
}

// The callback that receives the events.(static method)
DWORD  WINAPI EventSubscribeLog::SubscriptionCallback ( EVT_SUBSCRIBE_NOTIFY_ACTION action, PVOID pContext, EVT_HANDLE hEvent )
{
    DWORD status = ERROR_SUCCESS;
    PUSER_CONTEXT Callbackcontext = (PUSER_CONTEXT) pContext;
    EventSubscribeLog *handler = Callbackcontext->handler;
    DWORD *callBACKstatus = Callbackcontext->callBACKstatus;
    JNIEnv *temp_env = Callbackcontext->env;
    bool isEnvAttached = FALSE;
    JavaVM *callBackJVM;
    JNIEnv *callBackEnv;
    if (temp_env->GetJavaVM ( &callBackJVM ) < 0)
    {
        goto exit;
    }
    if (callBackJVM->AttachCurrentThread ( (void **) &callBackEnv, NULL ) < 0)
    {
        goto exit;
    }
    isEnvAttached = TRUE;
    if (action == EvtSubscribeActionError) {
        status = (DWORD) hEvent;
        handler->log ( javaEnv, L"\n The subscription callback received the following Win32 error: %lu", status );
        goto exit;
    }
    if (action == EvtSubscribeActionDeliver) {
        handler->SendEventToJDKPUSH ( hEvent, handler, callBackEnv );

    }
exit:
    if (isEnvAttached) {
        callBackJVM->DetachCurrentThread ( );
    }
    if (ERROR_SUCCESS != status) {
        *callBACKstatus = status;
    }
    return status; 
}

void EventSubscribeLog::SendEventToJDKPUSH ( EVT_HANDLE hEvent, EventSubscribeLog *handle, JNIEnv *watcherJNIEnv )
{
    PEVT_VARIANT RenderedValues = EventRender ( watcherJNIEnv, hEvent, 1 );
    if (RenderedValues != NULL) {
        __try {
            WORD EvtId = RenderedValues[EvtSystemEventID].UInt16Val;
            LPCWSTR EvtProviderName = RenderedValues[EvtSystemProviderName].StringVal;
            ULONGLONG I64Time = RenderedValues[EvtSystemTimeCreated].FileTimeVal;
            unsigned long EvtTimeCreated = FileTimeToUnixTime ( I64Time );
            unsigned long EvtTimeWritten = EvtTimeCreated;
            unsigned __int64 EvtRecordNumber = RenderedValues[EvtSystemEventRecordId].UInt64Val;
            WORD EvtCategory = RenderedValues[EvtSystemTask].UInt16Val;
            jobject
                eventHash = watcherJNIEnv->NewObject ( jClHashtable, jConHashtable ),
                jEvtCategory = watcherJNIEnv->NewObject ( intClass, intConID, EvtCategory ),
                jEvtCode = watcherJNIEnv->NewObject ( intClass, intConID, EvtId ),
                jEvtTimeGenerated = watcherJNIEnv->NewObject ( intClass, intConID, EvtTimeCreated ),
                jEvtTimeWritten = watcherJNIEnv->NewObject ( intClass, intConID, EvtTimeWritten ),
                jEvtRecordNumber = watcherJNIEnv->NewObject ( longClass, longConID, EvtRecordNumber ),

            watcherJNIEnv->CallObjectMethod ( eventHash, jMtdPutHashtable, jEvtCategoryKey, jEvtCategory );
            watcherJNIEnv->CallObjectMethod ( eventHash, jMtdPutHashtable, jEvtCodeKey, jEvtCode );
            watcherJNIEnv->CallObjectMethod ( eventHash, jMtdPutHashtable, jEvtTimeGeneratedKey, jEvtTimeGenerated );
            watcherJNIEnv->CallObjectMethod ( eventHash, jMtdPutHashtable, jEvtTimeWrittenKey, jEvtTimeWritten );
            watcherJNIEnv->CallObjectMethod ( eventHash, jMtdPutHashtable, jEvtRecordNumberKey, jEvtRecordNumber );

            watcherJNIEnv->CallStaticVoidMethod ( AppServerClass, evtNotify, eventHash ); //send event to java cache
            if (watcherJNIEnv->ExceptionOccurred ( ) != NULL) {
                log ( watcherJNIEnv, L"Exception occurred here in SendEventToJDKPUSH ...!" );
                watcherJNIEnv->ExceptionDescribe ( );
                watcherJNIEnv->ExceptionCheck ( );
                watcherJNIEnv->ExceptionClear ( );
            }
            watcherJNIEnv->DeleteLocalRef ( jEvtCategory );
            watcherJNIEnv->DeleteLocalRef ( jEvtCode );
            watcherJNIEnv->DeleteLocalRef ( jEvtTimeGenerated );
            watcherJNIEnv->DeleteLocalRef ( jEvtTimeWritten );
            watcherJNIEnv->DeleteLocalRef ( jEvtRecordNumber );
            watcherJNIEnv->DeleteLocalRef ( eventHash );
        } __except (EXCEPTION_EXECUTE_HANDLER) {
            log (  watcherJNIEnv,  L"Exception Caught in SendEventToJDKPUSH  %lu", GetExceptionCode ( ) );
        }
        goto exit;
    } else {
        log (  watcherJNIEnv,  L"Rendering Failed in SendEventToJDKPUSH" );
        goto exit;
    }
exit:
    free ( RenderedValues );
    RenderedValues = NULL;
}
PEVT_VARIANT EventSubscribeLog::EventRender(JNIEnv *javaEnv, EVT_HANDLE hEvent, int renderContextFlag)
{
    DWORD error = ERROR_SUCCESS;
    EVT_HANDLE hContext = NULL;
    DWORD dwBufferSize = 0;
    DWORD dwBufferUsed = 0;
    DWORD dwPropertyCount = 0;
    PEVT_VARIANT RenderedValues = NULL;
    BOOL ret = false;
    if (renderContextFlag == 1){
        hContext = EvtCreateRenderContext(0, NULL, EvtRenderContextSystem);
    }else{
        hContext = EvtCreateRenderContext(0, NULL, EvtRenderContextUser);
    }
    if (NULL == hContext){
        error = GetLastError();
        log( javaEnv, L"EventRender:EvtCreateRenderContext failed with %lu", error);
        goto exit;
    }
    ret = EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, RenderedValues, &dwBufferUsed, &dwPropertyCount);
    if (!ret){
        error = GetLastError();
        if (error == ERROR_INSUFFICIENT_BUFFER){
            dwBufferSize = dwBufferUsed;
            RenderedValues = (PEVT_VARIANT)malloc(dwBufferSize);
            if (RenderedValues){
                ret = EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, RenderedValues, &dwBufferUsed, &dwPropertyCount);
                if (!ret){
                    log( javaEnv, L"EventRender:EvtRender failed with %lu", error);
                }
            }else{
                log( javaEnv, L"EventRender:malloc failed");
                error = E_OUTOFMEMORY;
                goto exit;
            }
        }else{
            log( javaEnv, L"EventRender:EvtRender failed with %lu", error);
            goto exit;
        }
    }
exit:
    if (hContext) {EvtClose(hContext);}
    return RenderedValues;
}
void log ( JNIEnv *javaEnv, const wchar_t* message, ... ) //For JAVA Log method
{
    va_list args;
    int len;
    wchar_t * buffer;
    va_start ( args, message );
    len = _vscwprintf ( message, args ) + 1;
    buffer = (wchar_t*) malloc ( len * sizeof ( wchar_t ) );
    vswprintf ( buffer, message, args );
    jstring jsMessage = javaEnv->NewString ( (jchar*) buffer, wcslen ( buffer ) );
    javaEnv->CallStaticVoidMethod ( LogClass, LogMethod,  jsMessage );
    free ( buffer );
    javaEnv->DeleteLocalRef ( jsMessage );
}

在Java中

public static void log( String message) {
    nativeLogger.log(Level.WARNING, message);
}

异常追踪:

java.lang.StackOverflowError
    at evetsubscribepush.log(evetsubscribepush.java:XX)

我得到的就是Exception trace。

0 个答案:

没有答案