OS/2, eCS & ArcaOS - Technical > Programming

OW, JNI (GCC built java 1.6) and parameters

(1/3) > >>

Jan-Erik Lärka:
Hello,
I've now looked into how to use java 1.6 and with the help of the answer to the issue I posted quite some time ago, now managed to turn off floating point instructions.
Would appreciate if you can tell me how to also overcome the problem to feed the java code with one or more parameter(s).

LoadLib has been tested to dynamically load and use the dll for SQLite3 and Cairo, both the OW and GCC builds (the gcc builds installed with current ANPM) without recompile in between. The example code I used with SQLite3 and Cairo loaded with parameter "false" as they don't need the floating point fix. :-)
Try with OW as you like, but don't blame me if you run into problems.

Ohh, anyone that would like to help me to write code in vxrexx for this?
A gui to use java in the background etc.


--- Code: ---#define INCL_DOS
#define INCL_DOSMODULEMGR
#define INCL_DOSMISC
#define INCL_DOSERRORS
#include <os2.h>
#include <stdio.h>
#include <ctype.h>
#include <jni.h>
#include <stdlib.h>
#include <iostream>
#include "LoadLib.hpp"

LoadLib *javm;
ULONG rc;

JNIEnv* create_vm() {
    javm = new LoadLib( "client\\jvm" );//, ".", false ); //when used with sqlite3 and cairo
    if( javm->rc == NO_ERROR ) {
        JavaVM* jvm;
        JNIEnv* env;

        JavaVMOption options[] = {
            { "-Xmx512m", NULL },
            { "-XX:+TraceClassLoading", NULL },//To see the origin of the problem class
            { "-Djava.class.path=.", NULL },  //D:\\Programs\\vxrexx\\projects\\ODBCADMN\\j4o";
            { "-Djava.library.path=.", NULL },// set native library path
            { "-Djava.compiler=NONE", NULL }, // disable JIT
            { "-verbose:gc", NULL },          // print gc messages
            { "-verbose:jni", NULL },         // print JNI-related messages
            { "-verbose:class", NULL }        // print class loading messages
        };

        JavaVMInitArgs args;
        args.version = JNI_VERSION_1_6;
        args.nOptions = sizeof( options ) / sizeof( JavaVMOption );
        args.options = options;
        args.ignoreUnrecognized = JNI_FALSE;

        InitFunc( javm->hmod, jint, JNI_CreateJavaVM, ( JavaVM **p_vm, void **p_env, void *vm_args ) );
        jint jrc = JNI_CreateJavaVM( &jvm, (void**)&env, &args );
//#ifdef __WATCOMC__
        if( jrc != JNI_OK )
            cerr << "Problems loading JVM" << endl;
        else
            cout << "JVM has been loaded sucessfully" << endl;
//#endif
        delete options;
        return env;
    }
    return NULL;
}

void invoke_class( JNIEnv* env ) {
  cout << "invoke class" << endl;

  jclass helloWorldClass;
  jmethodID mainMethod;
  jobjectArray applicationArgs;
  jstring applicationArg0;

  cout << "FindClass HelloWorld" << endl;
  helloWorldClass = env->FindClass( "HelloWorld" );

  cout << "main helloWorld" << endl;
  mainMethod = env->GetStaticMethodID( helloWorldClass, "main", "([Ljava/lang/String;)V" );

  cout << "New Args" << endl;
  applicationArgs = env->NewObjectArray( 1, env->FindClass( "java/lang/String" ), NULL );
  cout << "New UTF String to test parameters" << endl;
  applicationArg0 = env->NewStringUTF( "testparam" );
  cout << "Args" << endl;
  env->SetObjectArrayElement( applicationArgs, 0, applicationArg0 ); //KABOOM! Unless commented out. :-(

  cout << "void main" << endl;
  env->CallStaticVoidMethod( helloWorldClass, mainMethod, applicationArgs);
}

int main( int argc, char **argv ) {
    JNIEnv* env = create_vm();
    if( env )
        invoke_class( env );
    else
        return 1;
  return 0;
}
--- End code ---

Lars:
Sorry I cannot help with your initial problem but you cannot use DosSetExceptionHandler / DosUnsetExceptionHandler the way you do because the exception registration record ("ex") has to be placed on the stack.
For what you did, it'll go into the heap. You will have to expose this parameter (address) at the constructor so that you can set it in the constructor.

Jan-Erik Lärka:
Interesting...

as I received "divide by zero" messages without it, the initial problem went away and was replaced by "inexact result" as I added the case for divide by zero, but all float-related went away as I added the other XCPT_FLOAT_... cases.

Would appreciate if you could give me a brief example how it should be resolved.

Regards,
//Jan-Erik

Lars:
1) catching the exception will work (as you observed). However, you will break the exception handler chaining if you do not place the exception registration record on the stack. That might lead to some odd effects (remember there is a default exception handler that the OS installs in order to catch exceptions in your program).

2) As far as I can tell from your code, the only reason that you need to catch exceptions is so that you can reset the FPU controls flags to turn back off FP exceptions. I am no C++ expert. I see these solutions (from best to worst)
a) have a look at C++ exceptions. I would hope that they allow to catch HW exceptions. But I don't know how you would be able to continue program execution from the point of exception
b) write C macros to set up and remove exception handlers. This is how XWorkplace does it and it works just fine. In the following example, for your case, you will not need to use setjmp/longjmp because you can always continue execution from the point of exception:

typedef struct _EXCEPTIONREGISTRATIONRECORD2
{
    EXCEPTIONREGISTRATIONRECORD reg;
    jmp_buf                                 jmp;
} EXCEPTIONREGISTRATIONRECORD2, *PEXCEPTIONREGISTRATIONRECORD2;

extern ULONG APIENTRY ExceptionHandler(
                                    PEXCEPTIONREPORTRECORD pRep,
                                    PEXCEPTIONREGISTRATIONRECORD2 pReg,
                                    PCONTEXTRECORD pCtx,
                                    PVOID pDispCtx);

#define TRY(except)                                                                     \
{                                                                                              \
    EXCEPTIONREGISTRATIONRECORD2 except={0};                                \
    except.reg.ExceptionHandler = (ERR)ExceptionHandler;                       \
    DosSetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&except);   \
    if (setjmp(except.jmp) == 0) {

#define CATCH()                                                                          \
    } else {

#define ENDTRY(except)                                                                     \
    }                                                                                               \
    DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&except);    \
}

...

ULONG APIENTRY ExceptionHandler(
                                    PEXCEPTIONREPORTRECORD pRep,
                                    PEXCEPTIONREGISTRATIONRECORD2 pReg,
                                    PCONTEXTRECORD pCtx,
                                    PVOID pDispCtx)
{
    if (pRep->fHandlerFlags & (EH_EXIT_UNWIND|EH_UNWINDING|EH_NESTED_CALL))
    {
        return XCPT_CONTINUE_SEARCH;
    }

    switch (pRep->ExceptionNum)
    {
        case XCPT_ACCESS_VIOLATION:
        case XCPT_ILLEGAL_INSTRUCTION:
        case XCPT_PRIVILEGED_INSTRUCTION:
        case XCPT_INVALID_LOCK_SEQUENCE:
        case XCPT_INTEGER_DIVIDE_BY_ZERO:
        case XCPT_INTEGER_OVERFLOW:
        case XCPT_FLOAT_DIVIDE_BY_ZERO:
        case XCPT_FLOAT_OVERFLOW:
        case XCPT_FLOAT_UNDERFLOW:
        case XCPT_FLOAT_INVALID_OPERATION:
        case XCPT_FLOAT_DENORMAL_OPERAND:
        case XCPT_FLOAT_INEXACT_RESULT:
        case XCPT_FLOAT_STACK_CHECK:
            longjmp(pReg->jmp,1);

        default:
            break;
    }
    return XCPT_CONTINUE_SEARCH;
}


c) allocate an exception registration record on the stack and pass the address to your constructor. In the constructor, register the handler and save the address of the exception registration record to a private variable. Then, in the destructor use that address to deregister the exception handler.

Lars

Dave Yeo:
Is this to work around the FPU Control Word bug? If so, perhaps this, taken from the Cairo init code, and perhaps the reason that Cairo works OK for you.

--- Code: ---    /* Workaround a bug in some OS/2 PM API calls that
     * modify the FPU Control Word but fail to restore it.
     */
    usCW = _control87 (0, 0);
    usCW = usCW | EM_INVALID | 0x80;
    _control87 (usCW, MCW_EM | 0x80);

--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version