SNI API

This chapter describes the SNI (Simple Native Interface) API. For more information on SNI specification, see Native Interface Mechanisms documentation.

The following API corresponds to architecture version 8.5.0.

sni.h

Defines

SNI_VERSION (0x010400)
JTRUE (1)
JFALSE (0)
JNULL (0)
SNI_IGNORED_RETURNED_VALUE (0)
SNI_OK (0)
SNI_ERROR (-1)
SNI_ILLEGAL_ARGUMENT (-2)
SNI_getArrayLength(array) (*((jint*)(((uint8_t*)(array))-sizeof(jint))))

Functions

bool SNI_isImmortalArray(void *javaArray)

Checks if the given Java array is immortal.

An immortal Java array remains at a fixed memory location and will not be moved or changed by Java’s garbage collection routine.

An immortal Java array can be used safely from another native task, an interrupt handler or can be used as a DMA buffer.

A non-immortal Java array can be used only during the execution of an SNI native or an SNI callback.

A reference to a non-immortal Java array must not be kept in C between two SNI native executions.

Parameters:

javaArray – is a Java array retrieved from an SNI native arguments.

Returns:

true if the given Java array is immortal or null, otherwise returns false.

int32_t SNI_throwNativeException(int32_t errorCode, const char *message)

Throws a new ej.sni.NativeException after the end of the current native method or SNI callback. NativeException class is a subclass of java.lang.RuntimeException. NativeException instances are unchecked exceptions, they do not need to be declared in the native method throws clause.

The virtual machine keeps a reference to the message until the end of the current native and does a copy of the message only when the current native returns. The message pointer must not reference a memory allocated locally in the stack.

If the current Java thread is suspended this function returns SNI_ERROR and no exception is thrown.

Calling this function while an exception is already pending will replace the previous exception.

If there is not enough space in the Java heap to allocate the exception, then an OutOfMemoryError will be thrown in Java.

Parameters:
  • errorCode – value that can be retrieved in Java using the NativeException.getErrorCode() method.

  • message – is a null-terminated string that will be used to generate the message returned by NativeException.getMessage(). May be null.

Returns:

SNI_OK on success. Returns SNI_ERROR if this function is not called within the virtual machine task or if the current thread is suspended.

int32_t SNI_throwNativeIOException(int32_t errorCode, const char *message)

Throws a new ej.sni.NativeIOException after the end of the current native method or SNI callback. NativeIOException class is a subclass of java.io.IOException. NativeIOException instances are checked exceptions, they need to be declared in the native method throws clause (e.g., throws IOException).

If the native method declaration is not compatible with NativeIOException (i.e., the throws clause does not specify NativeIOException or one of its superclasses) then a code>NativeException is thrown instead.

The virtual machine keeps a reference to the message until the end of the current native and does a copy of the message only when the current native returns. The message pointer must not reference a memory allocated locally in the stack.

If the current Java thread is suspended this function returns SNI_ERROR and no exception is thrown.

Calling this function while an exception is already pending will replace the previous exception.

If there is not enough space in the Java heap to allocate the exception, then an OutOfMemoryError will be thrown in Java.

Parameters:
  • errorCode – is a value that can be retrieved in Java using the NativeIOException.getErrorCode() method.

  • message – a null-terminated string that will be used to generate the message returned by NativeIOException.getMessage() method. May be null.

Returns:

SNI_OK on success. Returns SNI_ERROR if this function is not called within the virtual machine task or if the current thread is suspended.

bool SNI_isExceptionPending(void)

Checks if an exception is pending in the current Java thread (i.e., a successful call to SNI_throwNativeException or SNI_throwNativeIOException has been made prior to this call).

Returns:

true if an exception is pending in the current Java thread, returns false otherwise.

int32_t SNI_clearPendingException(void)

Clears any pending exception for the current Java thread.

Returns:

SNI_OK on success. Returns SNI_ERROR if the function is not called within the virtual machine task.

int32_t SNI_registerResource(void *resource, SNI_closeFunction close, SNI_getDescriptionFunction getDescription)

This function must be called when a native resource (file, socket, …) has been created to register it in the virtual machine.

The virtual machine keeps track of the native resources to prevent any memory leak when the virtual machine or an application is stopped.

In a Multi-Sandbox environment with KF profile enabled, the given close function is called when the application that has created the resource is stopped. If the resource has been created by the Kernel or if KF profile is disabled, the close function is called when the virtual machine stops.

To unregister the given native resource, call SNI_unregisterResource().

A native resource is uniquely identified by the pair resource, close. Several native resources with the same resource value can be registered as long as close is different.

If a native resource is registered several times with the same resource and close values, this function returns SNI_ILLEGAL_ARGUMENT (unless it has been unregistered before a second registration).

This function can be called once per native call. Calling this function several times within the same native will return SNI_ERROR.

If an error occurs while registering the resource at the end of the native, then the close function is called and an exception is thrown when returning in Java.

Parameters:
  • resource – the created native resource to register.

  • close – the function called if the virtual machine wants to automatically close the resource.

  • getDescription – the function called if the virtual machine wants to retrieve a description of the native resource. This pointer function may be null.

Returns:

SNI_OK on success. Returns SNI_ILLEGAL_ARGUMENT if close is null or if the given native resource has already been registered. Returns SNI_ERROR if the function is not called within the virtual machine task or if this function has been called several times in the same native.

int32_t SNI_unregisterResource(void *resource, SNI_closeFunction close)

This function must be called when a native resource previously registered with SNI_registerResource() has been reclaimed. It will unregister the given native resource so the virtual machine won’t call later the close function.

This method does not call the close function. It is up to the caller to call the appropriate function to close the resource.

The close parameter is used to uniquely identify the registered resource. If the given native resource is not found, this function returns SNI_ILLEGAL_ARGUMENT.

Parameters:
Returns:

SNI_OK on success. Returns SNI_ILLEGAL_ARGUMENT if the given native resource is not registered. Returns SNI_ERROR if the function is not called within the virtual machine task.

int32_t SNI_registerScopedResource(void *resource, SNI_closeFunction close, SNI_getDescriptionFunction getDescription)

Registers a scoped native resource.

These native resources are similar to standard native resources except they consume less memory, they are faster and they are closed automatically when the native returns back to Java. This function should be used when a resource is allocated in a native and released in a callback of the same native. This will prevent memory leaks that can occur when a thread is suspended using SNI_suspendCurrentJavaThreadWithCallback() and the virtual machine or the current application is stopped.

In a Multi-Sandbox environment with KF profile enabled, the given close function is also called when the application that has created the scoped native resource is stopped. If the scoped native resource has been created by the Kernel or if KF profile is disabled, the close function is called when the virtual machine stops.

To unregister the given scoped native resource, call SNI_unregisterScopedResource().

If several scoped native resources are registered within the same native context (or subsequent callback), then this function returns SNI_ERROR (unless the previously registered scoped native resource has been unregistered).

Parameters:
  • resource – the created scoped native resource to register.

  • close – the function called when the native returns back to Java.

  • getDescription – the function called if the virtual machine wants to retrieve a description of the scoped native resource. This pointer function may be null.

Returns:

SNI_OK on success. Returns SNI_ILLEGAL_ARGUMENT if close is null. Returns SNI_ERROR if the function is not called within the virtual machine task or if this function has been called several time in the same native context.

int32_t SNI_unregisterScopedResource(void)

Unregisters the scoped native resource previously registered with SNI_registerScopedResource().

After a call to this function, a new scoped native resource can be registered.

Usually this function does not need to be called because the registered scoped native resource is automatically closed and unregistered when the native returns back to Java.

This method does not call the close function given previously to SNI_registerScopedResource(). It is up to the caller to call the appropriate function to close the resource.

Returns:

SNI_OK on success. Returns SNI_ERROR if the function is not called within the virtual machine task or if no scoped native resource has been previously registered.

int32_t SNI_getScopedResource(void **resourcePtr, SNI_closeFunction *closePtr, SNI_getDescriptionFunction *getDescriptionPtr)

Gets the information of the scoped native resource previously registered with SNI_registerScopedResource().

Parameters:
  • resourcePtr – output parameter. This function will store in this pointer the resource value previously given to SNI_registerScopedResource(). May be null.

  • closePtr – output parameter. This function will store in this pointer the close value previously given to SNI_registerScopedResource(). May be null.

  • getDescriptionPtr – output parameter. This function will store in this pointer the getDescription value previously given to SNI_registerScopedResource(). May be null.

Returns:

SNI_OK on success. Returns SNI_ERROR if the function is not called within the virtual machine task or if no scoped native resource has been previously registered.

int32_t SNI_retrieveArrayElements(jbyte *java_array, jint java_start, jint java_length, int8_t *buffer, uint32_t buffer_length, int8_t **out_buffer, uint32_t *out_length, bool refresh_content)

Gets the body of a Java byte array so it can be used outside of the scope of the current native function.

If the given Java array is an immortal array, then out_buffer is set to reference directly the element at the offset java_start in the given Java array and out_length is set to java_length. If the given Java array is not an immortal array, then out_buffer is set to reference buffer, *out_length is set to the smaller value of java_length and buffer_length, and then, if refresh_content is true, *out_length bytes are copied from the content of the Java array into buffer.

Since the returned array may be a copy of the Java array, changes made to the returned array will not necessarily be reflected in the original Java array until SNI_flushArrayElements() is called.

The function SNI_flushArrayElements() doesn’t have to be called if changes made to the returned array don’t need to be reflected in the original Java array.

Parameters:
  • java_array – the Java array.

  • java_start – the start offset in array java_array of the first element to get.

  • java_length – the maximum number of bytes to get.

  • buffer – the buffer to use if the given Java array is not immortal.

  • buffer_length – length in bytes of buffer.

  • out_buffer – output pointer to the retrieved elements.

  • out_length – the number of elements retrieved.

  • refresh_content – specifies whether or not the retrieved array will be initialized with the elements of the given Java array.

Returns:

SNI_OK on success. Returns SNI_ILLEGAL_ARGUMENT if java_start is negative, java_length is negative, java_length is greater than SNI_getArrayLength(java_array) - java_start, or one of the given pointers is null.

int32_t SNI_flushArrayElements(jbyte *java_array, jint java_start, jint java_length, int8_t *buffer, uint32_t buffer_length)

If necessary, this function copies back all the content of buffer to the Java array.

If the given Java array is an immortal array, this function does nothing. If the given Java array is not an immortal array, then this function copies back all the content of buffer to the Java array at the offset java_start.

Parameters:
  • java_array – the Java array.

  • java_start – the start offset in array java_array of the first element to release.

  • java_length – the maximum number of bytes to release.

  • buffer – the buffer to use if the given Java array is not immortal.

  • buffer_length – length in bytes of buffer.

Returns:

SNI_OK on success. Returns SNI_ILLEGAL_ARGUMENT if java_start is negative, java_length is negative, java_length is greater than SNI_getArrayLength(java_array) - java_start, buffer_length is greater than java_length, or one of the given pointers is null.

void *SNI_createVM(void)

Creates and initializes a virtual machine. This function MUST be called once before a call to SNI_startVM().

Only one instance of the virtual machine can be created in the system, and both SNI_createVM() and SNI_destroyVM() should only be called once.

Returns:

null if an error occurred, otherwise returns a virtual machine instance.

int32_t SNI_startVM(void *vm, int32_t argc, char **argv)

Starts the specified virtual machine and calls the main() method of the Java application with the given String arguments. This function returns when the Java application ends.

The Java application ends when all the non-daemon threads are terminated or when the Java method System.exit(int) is called.

To restart the application, call again the SNI_startVM() function without calling SNI_createVM() or SNI_destroyVM() before.

Parameters:
  • vm – a pointer returned by the SNI_createVM() function.

  • argc – number of string arguments in argv.

  • argv – array of string arguments given to the Java main() method. May be null.

Returns:

0 when the virtual machine ends normally or a negative value when an error occurred (see constant values LLMJVM_E_* defined in LLMJVM.h).

int32_t SNI_getExitCode(void *vm)

Call this function after virtual machine execution to get the Java application exit code.

Parameters:

vm – a pointer returned by the SNI_createVM() function.

Returns:

the value given to the System.exit(exitCode) or 0 if the Java application ended without calling System.exit(exitCode).

void SNI_destroyVM(void *vm)

Releases all the virtual machine resources. This function must be called after the return of the function SNI_startVM(). The vm pointer is no longer valid after this call.

Only one instance of the virtual machine can be created in the system, and both SNI_createVM() and SNI_destroyVM() should only be called once.

Parameters:

vm – a pointer returned by the SNI_createVM() function.

int32_t SNI_getCurrentJavaThreadID(void)

Gets the ID of the current Java thread.

The returned ID is the same than the one returned by the Java method Thread.getId().

Returns:

the ID of the current Java thread or SNI_ERROR if this function is not called within the virtual machine task.

int32_t SNI_suspendCurrentJavaThread(int64_t timeout)

Causes the current Java thread to pause its Java execution after the end of the current native method. This function is not blocking. The current Java thread will resume its execution after the reception of an external event or after timeout milliseconds.

If the pending resume flag of the current Java thread is set, the Java thread is not suspended and its pending resume flag is cleared (see SNI_isResumePending()).

If an exception is pending, the thread is not suspended and this function returns SNI_ERROR.

The result of calling this function several times during the same native execution is unpredictable.

Parameters:

timeout – duration in milliseconds of the pause. If timeout is zero, the thread waits forever until resumed.

Returns:

SNI_OK if the request is accepted. Returns SNI_ERROR if this function is not called within the virtual machine task or if an exception is pending.

int32_t SNI_suspendCurrentJavaThreadWithCallback(int64_t timeout, SNI_callback sniCallback, void *callbackSuspendArg)

Causes the current Java thread to pause its Java execution after the end of the current native method. This function is not blocking. The current Java thread will resume its execution after the reception of an external event or after timeout milliseconds.

If a non-null SNI callback is specified, then this callback is called when the Java thread is resumed. The callback must have the same signature as the current executed native (same parameters and same return type). The callback will be executed in the virtual machine task.

The value given to callbackSuspendArg can be retrieved in the SNI callback using SNI_getCallbackArgs().

If the pending resume flag of the current Java thread is set, the Java thread is not suspended and its pending resume flag is cleared (see SNI_isResumePending()).

If an exception is pending, the thread is not suspended, this function returns SNI_ERROR, and the callback is not called.

The result of calling this function several times during the same native execution is unpredictable.

Parameters:
  • timeout – duration in milliseconds of the pause. If timeout is zero, the thread waits forever until resumed.

  • sniCallback – function called when the Java thread is resumed. May be null.

  • callbackSuspendArg – argument that can be retrieved in the callback using SNI_getCallbackArgs(). May be null.

Returns:

SNI_OK if the request is accepted. Returns SNI_ERROR if this function is not called within the virtual machine task or if an exception is pending.

int32_t SNI_javaThreadYield(SNI_callback sniCallback, void *callbackArg)

Causes the current Java thread to yield its execution to another Java thread after the end of the current native method and then to call the given callback when it will be scheduled again.

The callback must have the same signature as the current executed native (same parameters and same return type). The callback will be executed in the virtual machine task.

This function can be used to split the execution of a long native method into several increments leaving some execution time to other Java threads.

If an exception is pending, this function returns SNI_ERROR, and the callback is not called.

The result of calling this function several times during the same native execution is unpredictable.

Parameters:
  • sniCallback – function called when the Java thread is scheduled again. May be null.

  • callbackArg – argument that can be retrieved in the callback using SNI_getCallbackArgs(). May be null.

Returns:

SNI_OK on success. Returns SNI_ERROR if this function is not called within the virtual machine task or if an exception is pending.

int32_t SNI_getCallbackArgs(void **callbackSuspendArgPtr, void **callbackResumeArgPtr)

Retrieves the arguments given to an SNI callback with the function SNI_javaThreadYield(), SNI_suspendCurrentJavaThreadWithCallback() or SNI_resumeJavaThreadWithArg().

This function should be called in an SNI callback. If the functions SNI_suspendCurrentJavaThreadWithCallback() or SNI_javaThreadYield() have not been called previously for the current native or one of its callback, the value returned in callbackSuspendArgPtr is undefined. If the function SNI_resumeJavaThreadWithArg() has not been called previously for the current native or one of its callback, the value returned in callbackResumeArgPtr is undefined.

Parameters:
Returns:

SNI_OK on success. Returns SNI_ERROR if this function is not called within the virtual machine task.

int32_t SNI_resumeJavaThread(int32_t javaThreadID)

Resumes the given Java thread if it is suspended. If the Java thread is not suspended, its pending resume flag is set and the next call of SNI_suspendCurrentJavaThread() will not suspend the thread.

Parameters:

javaThreadID – ID of the Java thread to resume. The Java thread ID can be retrieved using SNI_getCurrentJavaThreadID() function.

Returns:

SNI_ERROR if the given Java thread ID is invalid, otherwise returns SNI_OK.

int32_t SNI_resumeJavaThreadWithArg(int32_t javaThreadID, void *callbackResumeArg)

Resumes the given Java thread if it is suspended. If the Java thread is not suspended, its pending resume flag is set and the next call of SNI_suspendCurrentJavaThread() will not suspend the thread.

Parameters:
Returns:

SNI_ERROR if the given Java thread ID is invalid, otherwise returns SNI_OK.

bool SNI_isResumePending(int32_t javaThreadID)

Tests whether the given Java thread has been resumed while it was not suspended.

The pending resume flag is set when calling SNI_resumeJavaThread() or SNI_resumeJavaThreadWithArg(). It is cleared when calling SNI_suspendCurrentJavaThread() or SNI_suspendCurrentJavaThreadWithCallback(), or when the Java thread actually resumes its execution. The pending resume flag is not modified by a timeout that occurs during a pause.

The pending resume flag of the given Java thread is unaffected by this method.

If the given Java thread ID is invalid, this method does nothing and returns false.

Parameters:

javaThreadID – ID of the Java thread to test. The Java thread ID can be retrieved using SNI_getCurrentJavaThreadID() function.

Returns:

true if the pending resume flag of the given Java thread is set, false otherwise.

bool SNI_clearCurrentJavaThreadPendingResumeFlag(void)

Clears the pending resume flag of the current Java thread (see SNI_isResumePending()).

If this method is not called within the virtual machine task, it does nothing and returns false.

Returns:

true if the pending resume flag of the current Java thread was set before clearing it, false otherwise.