Oneiros
Oneiros

Reputation: 4378

JNI Native Method causing VM crashing

I'm implementing a Java method as Native in C++

JNIEXPORT jobjectArray JNICALL myMethod(JNIEnv *env, jclass, //parameters){

    int** result = //my function to obtain a matrix n x m of integers
    std::vector<jint> tmp;

    //fill the vector tmp with matrix integers and deallocate the matrix
    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            tmp[m*i + j] = result[i][j];
        }
        free(result[i]);
    }
    free(result);

    jintArray jResults = env->NewIntArray( tmp.size() );
    env->SetIntArrayRegion( jResults, 0, tmp.size(), &tmp[0] );
    return env->NewObjectArray(tmp.size(), env->GetObjectClass(jResults), 0);
}

It compiles fine and java loads the dll successfully. But i get this error at runtime:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x10009a7d, pid=2264, tid=3856
#
# JRE version: 7.0-b147
# Java VM: Java HotSpot(TM) Client VM (21.0-b17 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [myDLL.dll+0x9a7d]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as: hs_err_pid2264.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Java result 1

Any idea?

Upvotes: 0

Views: 2809

Answers (4)

Richard
Richard

Reputation: 51

You may try to use the Java VM option -Xcheck:jni. The detail can be found at www.oracle.com/technetwork/java/javase/clopts-139448.html#gbmtq.

Upvotes: 0

bobby
bobby

Reputation: 2789

I have my doubts regarding whether you can return an int[] as an object array. In particular the line env->GetObjectClass(jResults) seems suspicious to me. This line tries to get the class for int[], which is one which doesn't exist to my knowledge. My suggestion are to either return an Integer[], and to thereby get the class by using env->GetObjectClass("java/lang/Integer), or change the method signature to jintArray. As far as i know, jintArray != jobjectArray.

Upvotes: 0

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145359

Your current code as I'm writing this:

JNIEXPORT jobjectArray JNICALL myMethod(JNIEnv *env, jclass, //parameters){

    int** result = //my function to obtain a matrix n x m of integers
    std::vector<jint> tmp;

    //fill the vector tmp with matrix integers and deallocate the matrix
    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            tmp[m*i + j] = result[i][j];
        }
        free(result[i]);
    }
    free(result);

    jintArray jResults = env->NewIntArray( tmp.size() );
    env->SetIntArrayRegion( jResults, 0, tmp.size(), &tmp[0] );
    return env->NewObjectArray(tmp.size(), env->GetObjectClass(jResults), 0);
}

In this code you're accessing various elements of a zero-size vector tmp.

A std::vector is not an associative array; it's an ordinary contiguous array. Hence you need to either size it up front, or use the push_back method to add new elements. You can specify a size like this:

std::vector<jint> tmp( m*n );

Cheers & hth.,

Upvotes: 2

hmakholm left over Monica
hmakholm left over Monica

Reputation: 23342

You never initialize the result variable, so your code ends up trying to read from garbage addresses, and then trying to free pointers it has read from a garbage address.

(Oh, never mind, there was hidden code...)

Upvotes: 0

Related Questions