JNI problem - inserting array elements

Started by CaptainJester, January 09, 2005, 22:38:43

Previous topic - Next topic

CaptainJester

First the code:
/*
 * Class:     org_lwjgl_devil_ILU
 * Method:    iluRegionfv
 * Signature: ([Lorg/lwjgl/devil/ILpointf;I)V
 */
JNIEXPORT void JNICALL Java_org_lwjgl_devil_ILU_iluRegionfv(JNIEnv *env, jclass clazz, jobjectArray points, jint n) {
    jfieldID fieldId;
    jmethodID methodId;
    jobject element;
    int i;
    ILpointf *pointInfo;

    if(points == 0) {
        throwException(env, "ILpointf array must not be null.");
    }

    pointInfo = (ILpointf *)malloc(sizeof(ILpointf) * n);
    iluGetImageInfo(pointInfo, n);

    clazz = (*env)->FindClass(env, "org/lwjgl/devil/ILpointf");
    methodId = (*env)->GetMethodID(env, clazz, "<init>", "()V");

    for(i=0;i<n;i++) {
        element = (*env)->NewObject(env, clazz, methodId);

        fieldId = (*env)->GetFieldID(env, clazz, "x", "F");
        (*env)->SetFloatField(env, element, fieldId, (jfloat)((pointInfo + i)->x));

        fieldId = (*env)->GetFieldID(env, clazz, "y", "F");
        (*env)->SetFloatField(env, element, fieldId, (jfloat)((pointInfo + i)->y));

        //problem line below
        (*env)->SetObjectArrayElement(env, points, i, element);
    }

    free(pointInfo);
}

The jobjectArray, points, has been allocated on the Java side with:
ILpointf pointf[] = new ILpointf[3];

I have checked the address of points and element and both are not NULL.  The counter varialbe 'i' is 0.

The function: (*env)->SetObjectArrayElement(env, points, i, element); will insert the value 'element' at index 'i' in array 'points'.  According to the docs that is what it is supposed to do.  However, it is throwing an exception.
Here is the exception:
Quote
Unexpected Signal : EXCEPTION_ACCESS_VIOLATION (0xc0000005) occurred at PC=0x80360E7
Function=[Unknown.]
Library=F:\Program Files\Java\j2re1.4.2_04\bin\client\jvm.dll

NOTE: We are unable to locate the function name symbol for the error
     just occurred. Please refer to release documentation for possible
     reason and solutions.


Current Java thread:
   at org.lwjgl.devil.ILU.iluRegionfv(Native Method)
   at org.lwjgl.test.devil.BasicTest.main(BasicTest.java:109)

Dynamic libraries:
0x00400000 - 0x00407000    F:\Program Files\Java\j2re1.4.2_04\bin\javaw.exe
0x77F50000 - 0x77FF7000    F:\WINDOWS\System32\ntdll.dll
0x77E60000 - 0x77F46000    F:\WINDOWS\system32\kernel32.dll
0x77DD0000 - 0x77E5D000    F:\WINDOWS\system32\ADVAPI32.dll
0x78000000 - 0x78087000    F:\WINDOWS\system32\RPCRT4.dll
0x77D40000 - 0x77DCC000    F:\WINDOWS\system32\USER32.dll
0x7E090000 - 0x7E0D1000    F:\WINDOWS\system32\GDI32.dll
0x77C10000 - 0x77C63000    F:\WINDOWS\system32\MSVCRT.dll
0x08000000 - 0x08138000    F:\Program Files\Java\j2re1.4.2_04\bin\client\jvm.dll
0x76B40000 - 0x76B6C000    F:\WINDOWS\System32\WINMM.dll
0x10000000 - 0x10007000    F:\Program Files\Java\j2re1.4.2_04\bin\hpi.dll
0x00820000 - 0x0082E000    F:\Program Files\Java\j2re1.4.2_04\bin\verify.dll
0x00830000 - 0x00849000    F:\Program Files\Java\j2re1.4.2_04\bin\java.dll
0x00850000 - 0x0085D000    F:\Program Files\Java\j2re1.4.2_04\bin\zip.dll
0x02C40000 - 0x02DC8000    F:\Apps\DevIL\lib\DevIL.dll
0x02DD0000 - 0x02DE4000    F:\Apps\Java\eclipse\workspace\LWJGL\libs\lwjgl-devil.dll
0x02DF0000 - 0x02E04000    F:\Apps\DevIL\lib\ILU.dll
0x76C90000 - 0x76CB2000    F:\WINDOWS\system32\imagehlp.dll
0x6D510000 - 0x6D58D000    F:\WINDOWS\system32\DBGHELP.dll
0x77C00000 - 0x77C07000    F:\WINDOWS\system32\VERSION.dll
0x76BF0000 - 0x76BFB000    F:\WINDOWS\System32\PSAPI.DLL

Heap at VM Abort:
Heap
def new generation   total 576K, used 253K [0x10010000, 0x100b0000, 0x104f0000)
 eden space 512K,  49% used [0x10010000, 0x1004f6e0, 0x10090000)
 from space 64K,   0% used [0x10090000, 0x10090000, 0x100a0000)
 to   space 64K,   0% used [0x100a0000, 0x100a0000, 0x100b0000)
tenured generation   total 1408K, used 0K [0x104f0000, 0x10650000, 0x14010000)
  the space 1408K,   0% used [0x104f0000, 0x104f0000, 0x104f0200, 0x10650000)
compacting perm gen  total 4096K, used 1067K [0x14010000, 0x14410000, 0x18010000)
  the space 4096K,  26% used [0x14010000, 0x1411ade8, 0x1411ae00, 0x14410000)

Local Time = Sun Jan 09 17:30:57 2005
Elapsed Time = 0
#
# HotSpot Virtual Machine Error : EXCEPTION_ACCESS_VIOLATION
# Error ID : 4F530E43505002EF
# Please report this error at
# http://java.sun.com/cgi-bin/bugreport.cgi
#
# Java VM: Java HotSpot(TM) Client VM (1.4.2_04-b05 mixed mode)
#
# An error report file has been saved as hs_err_pid3824.log.
# Please refer to the file for further information.
#
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities.  We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
8)

Matzon

Can't spot the error - are you sure it's that particular method call that is the fault ?

Three things though:
1: Where do you actually call iluRegionfv ???
2: should 'points' not already contain the points? otherwise you get a lot of garbage
3: iluRegion<f/i>v is the only method to use the ILpoint<f/i> - you could probably just make the call into a iluRegion(FloatBuffer) and a iluRegion(IntBuffer) and then implement it using:
off the top of my head
public static void iluRegion(FloatBuffer buffer) {
  BufferChecks.checkBuffer(buffer, 3);
  niluRegion(buffer, buffer.position(), buffer.remaining(), IL.IL_FLOAT);
}

public static void iluRegion(IntBuffer buffer) {
  BufferChecks.checkBuffer(buffer, 3);
  niluRegion(buffer, buffer.position(), buffer.remaining(), IL.IL_INT);
}

private static native void niluRegion(Buffer buffer, int offset, int count, int type);

and then do a:
JNIEXPORT void JNICALL Java_org_lwjgl_devil_ILU_niluRegion(JNIEnv *env, jclass clazz, jobject buffer, jint offset, jint count, jint type) {
  if (type == IL_FLOAT) {
    ILpointf* points = safeGetBufferAddress(env, buffer, offset);
    iluRegionfv(points ,count);
  } else if (type == IL_INT) {
    ILpointi* points = safeGetBufferAddress(env, buffer, offset);
    iluRegioniv(points ,count);
  }
}

then the buffers will contain the x/y's interleaved...

it's not a OO as using point objects from java code - but it saves a hell of a lot of objects, and is in line with the rest of lwjgl.

CaptainJester

So then is it up to the user to populate ILpoint<f/i>?

I don't mind doing it that way if that is the way you have been doing it.
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities.  We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
8)

Matzon

Well, the user should never ude the ILpointX class - it's too simple to pack in a class. Normally when you pass data to ogl you interleave it as x/y/z/x/y/z - and I don't see any reason why Devil should be any different.

As user would thus do this:
IntBuffer region = BufferUtils.createIntBuffer(6);
ILU.iluRegion(region);

System.out.println("Point 1: " + region.get(0) + ", " + region.get(1));
System.out.println("Point 2: " + region.get(2) + ", " + region.get(3));
System.out.println("Point 3: " + region.get(4) + ", " + region.get(5));