Core supporting services for the FFI with Java

This module must be imported by modules using the Java FFI. Some might prefer to import the whole java package as it provides other useful services.

Introduced classes

extern class JavaException

java :: JavaException

Java class: java.lang.Exception
extern class JavaString

java :: JavaString

A standard Java string java.lang.String
extern class JavaThrowable

java :: JavaThrowable

Java class: java.lang.Throwable
extern class Java_nio_Buffer

java :: Java_nio_Buffer

Container for data of a specific primitive type
extern class Java_nio_ByteBuffer

java :: Java_nio_ByteBuffer

A byte buffer

Redefined classes

redef extern class CString

java :: ffi_support $ CString

C string char *
redef extern class JavaObject

java :: ffi_support $ JavaObject

Represens a jni jobject
redef extern class JniEnv

java :: ffi_support $ JniEnv

Represents a jni JNIEnv, which is a thread in a JavaVM
redef class Sys

java :: ffi_support $ Sys

The main class of the program.
redef abstract class Text

java :: ffi_support $ Text

High-level abstraction for all text representations

All class definitions

redef extern class CString

java :: ffi_support $ CString

C string char *
extern class JavaException

java $ JavaException

Java class: java.lang.Exception
redef extern class JavaObject

java :: ffi_support $ JavaObject

Represens a jni jobject
extern class JavaString

java $ JavaString

A standard Java string java.lang.String
extern class JavaThrowable

java $ JavaThrowable

Java class: java.lang.Throwable
extern class Java_nio_Buffer

java $ Java_nio_Buffer

Container for data of a specific primitive type
extern class Java_nio_ByteBuffer

java $ Java_nio_ByteBuffer

A byte buffer
redef extern class JniEnv

java :: ffi_support $ JniEnv

Represents a jni JNIEnv, which is a thread in a JavaVM
redef class Sys

java :: ffi_support $ Sys

The main class of the program.
redef abstract class Text

java :: ffi_support $ Text

High-level abstraction for all text representations
package_diagram java::ffi_support ffi_support jvm jvm java::ffi_support->jvm core core jvm->core ...core ... ...core->core java::collections collections java::collections->java::ffi_support java::io io java::io->java::ffi_support java::java java java::java->java::collections java::java... ... java::java...->java::java android::assets_and_resources assets_and_resources android::assets_and_resources->java::io android::assets_and_resources... ... android::assets_and_resources...->android::assets_and_resources

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module jvm

jvm :: jvm

Java Virtual Machine invocation API and others services from the JNI C API

Children

module collections

java :: collections

Basic Java collections
module io

java :: io

Services from the java.io package

Descendants

module a_star-m

a_star-m

module activities

android :: activities

Android Activities wrapper
module android

android :: android

Android services and implementation of app.nit
module android19

gamnit :: android19

Variation using features from Android API 19
module assets

android :: assets

Implementation of app::assets
module assets_and_resources

android :: assets_and_resources

Android Assets and Resources Management
module at_boot

android :: at_boot

Import this module to launch Service at device boot
module audio

android :: audio

Android audio services, wraps a part of android audio API
module bundle

android :: bundle

A mapping class of String to various value types used by the
module camera_control_android

gamnit :: camera_control_android

Two fingers camera manipulation, pinch to zoom and slide to scroll
module cardboard

android :: cardboard

Services from the Google Cardboard SDK for virtual reality on Android
module cardboard

gamnit :: cardboard

Update the orientation of world_camera at each frame using the head position given by android::cardboard
module dalvik

android :: dalvik

Java related services specific to Android and its Dalvik VM
module data_store

android :: data_store

Implements app::data_store using shared_preferences
module display_android

gamnit :: display_android

Gamnit display implementation for Android
module game

android :: game

Android services and implementation of app.nit for gamnit and mnit
module gamepad

android :: gamepad

Support for gamepad events (over Bluetooth or USB)
module gamnit_android

gamnit :: gamnit_android

Support services for Gamnit on Android
module http_request

android :: http_request

Android implementation of app:http_request
module input_events

android :: input_events

Pointer and hardware key events
module intent

android :: intent

Services allowing to launch activities and start/stop services using
module intent_api10

android :: intent_api10

Services allowing to launch activities and start/stop services using
module intent_api11

android :: intent_api11

Refines intent module to add API 11 services
module intent_api12

android :: intent_api12

Refines intent module to add API 12 services
module intent_api14

android :: intent_api14

Refines intent module to add API 14 services
module intent_api15

android :: intent_api15

Refines intent module to add API 15 services
module intent_api16

android :: intent_api16

Refines intent module to add API 16 services
module intent_api17

android :: intent_api17

Refines intent module to add API 17 services
module intent_api18

android :: intent_api18

Refines intent module to add API 18 services
module intent_api19

android :: intent_api19

Refines intent module to add API 19 services
module java

java :: java

Supporting services for the FFI with Java and to access Java libraries
module landscape

android :: landscape

Lock the application in the landscape orientation
module load_image

android :: load_image

Low-level services to load pixel data from the assets
module log

android :: log

Advanced Android logging services
module native_app_glue

android :: native_app_glue

Wrapper of the Android native_app_glue framework to implement app.nit
module native_notification

android :: native_notification

Native Java classes for notifications
module native_ui

android :: native_ui

Native services from the android.view and android.widget namespaces
module nit_activity

android :: nit_activity

Core implementation of app.nit on Android using a custom Java entry point
module notification

android :: notification

Services to show notification in the Android status bar
module platform

android :: platform

Triggers compilation for the android platform
module portrait

android :: portrait

Config to set the portrait orientation
module sensors

android :: sensors

Access Android sensors
module service

android :: service

Android service support for app.nit centered around the class Service
module shared_preferences

android :: shared_preferences

Services allowing to save and load datas to internal android device
module shared_preferences_api10

android :: shared_preferences_api10

Services to save/load data using android.content.SharedPreferences for the android platform
module shared_preferences_api11

android :: shared_preferences_api11

Refines shared_preferences module to add API 11 services
module toast

android :: toast

Services to display a toast, a small popup on Android
module ui

android :: ui

Views and services to use the Android native user interface
module ui_test

android :: ui_test

Test for app.nit's UI services
module vibration

android :: vibration

Vibration services for Android
module vr

gamnit :: vr

VR support for gamnit depth, for Android only
module wifi

android :: wifi

Simple wrapper of the Android WiFi services
# Core supporting services for the FFI with Java
#
# This module *must* be imported by modules using the Java FFI.
# Some might prefer to import the whole `java` package as it provides
# other useful services.
module ffi_support is
	cflags "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/"
	ldflags "-L $(JNI_LIB_PATH) -ljvm"
	new_annotation extra_java_files
	extra_java_files "nit.app.NitObject"
end

import jvm

redef class Sys
	private var jvm_cache: nullable JavaVM = null
	private var jni_env_cache: nullable JniEnv = null

	# Default Java Virtual Machine to use
	#
	# Instantiated using `create_default_jvm` if not already set.
	fun jvm: JavaVM
	do
		if jvm_cache == null then create_default_jvm
		return jvm_cache.as(not null)
	end

	# Sets the current default Java Virtual Machine (use with `jni_env=`)
	fun jvm=(jvm: JavaVM) do jvm_cache = jvm

	# Current main `JniEnv`
	fun jni_env: JniEnv
	do
		if jni_env_cache == null then create_default_jvm
		return jni_env_cache.as(not null)
	end

	# Sets the current default JNI env (use with `jvm=`)
	fun jni_env=(jni_env: JniEnv) do jni_env_cache = jni_env

	# Called by `jvm` and `jni_env` to instantiate a Java Virtual Machine.
	# Used mostly for the FFI with Java.
	protected fun create_default_jvm
	do
		var builder = new JavaVMBuilder

		# By default, look for Java classes in a jar file the same directory as the executable
		builder.options.add "-Djava.class.path={sys.program_name}.jar"

		var jvm = builder.create_jvm
		assert jvm != null else print "JVM creation failed"

		self.jvm = jvm
		assert not jvm.address_is_null
		self.jni_env = jvm.env
		assert not jni_env.address_is_null
	end

	# Get a Java class by its name from the current `jni_env`
	fun load_jclass(name: CString): JClass import jni_env `{
		JNIEnv *nit_ffi_jni_env = Sys_jni_env(self);

		// retrieve the implementation Java class
		jclass java_class = (*nit_ffi_jni_env)->FindClass(nit_ffi_jni_env, name);
		if (java_class == NULL) {
			fprintf(stderr, "Nit FFI with Java error: failed to load class.\\n");
			(*nit_ffi_jni_env)->ExceptionDescribe(nit_ffi_jni_env);
			exit(1);
		}

		return java_class;
	`}
end

# A standard Java string `java.lang.String`
#
# Converted to a Nit string using `to_s`, or to a C string with `to_cstring`.
# Created using `String::to_java_string` or `CString::to_java_string`.
extern class JavaString in "Java" `{ java.lang.String `}
	super JavaObject

	# Get the string from Java and copy it to Nit memory
	fun to_cstring: CString import sys, Sys.jni_env `{
		Sys sys = JavaString_sys(self);
		JNIEnv *env = Sys_jni_env(sys);

		// Get the data from Java
		const char *java_cstr = (*env)->GetStringUTFChars(env, self, NULL);
		jsize len = (*env)->GetStringUTFLength(env, self);

		// Copy it in control of Nit
		char *nit_cstr = (char*)malloc(len+1);
		memcpy(nit_cstr, java_cstr, len);
		nit_cstr[len] = '\0';

		// Free JNI ref and return
		(*env)->ReleaseStringUTFChars(env, self, java_cstr);
		return nit_cstr;
	`}

	redef fun to_s
	do
		if is_java_null then return "<{inspect_head}:null>"
		return to_cstring.to_s
	end
end

redef class CString
	# Get a Java string from this C string
	#
	# This instance is only valid until the next execution of Java code.
	# You can use `new_local_ref` to keep it longer.
	fun to_java_string: JavaString import sys, Sys.jni_env `{
		Sys sys = JavaString_sys(self);
		JNIEnv *env = Sys_jni_env(sys);
		return (*env)->NewStringUTF(env, self);
	`}
end

redef class Text
	# Get `self` as a `JavaString`
	fun to_java_string: JavaString do return to_cstring.to_java_string
end

redef extern class JavaObject

	# Returns a global reference to the Java object behind this reference
	#
	# You must use a global reference when keeping a Java object
	# across execution of Java code, per JNI specification.
	fun new_global_ref: SELF import sys, Sys.jni_env `{
		Sys sys = JavaObject_sys(self);
		JNIEnv *env = Sys_jni_env(sys);
		return (*env)->NewGlobalRef(env, self);
	`}

	# Delete this global reference
	fun delete_global_ref import sys, Sys.jni_env `{
		Sys sys = JavaObject_sys(self);
		JNIEnv *env = Sys_jni_env(sys);
		(*env)->DeleteGlobalRef(env, self);
	`}

	# Delete this local reference
	fun delete_local_ref import sys, Sys.jni_env `{
		Sys sys = JavaObject_sys(self);
		JNIEnv *env = Sys_jni_env(sys);
		(*env)->DeleteLocalRef(env, self);
	`}

	# Pops the current local reference frame and return a valid reference to self
	#
	# Similar to `JavaVM::pop_local_frame` but returns a value.
	fun pop_from_local_frame: SELF
	do
		var jni_env = sys.jni_env
		return pop_from_local_frame_with_env(jni_env)
	end

	# Java implementation of `pop_from_local_frame`
	protected fun pop_from_local_frame_with_env(jni_env: JniEnv): SELF `{
		return (*jni_env)->PopLocalFrame(jni_env, self);
	`}

	# Is `self` null in Java?
	#
	# Since Java type system doesn't have the same `nullable` concept as Nit's,
	# the two systems are not directly compatible. Any Nit instances of
	# `JavaObject` may hold a Java null.
	#
	# To benefit from the safer type system of Nit, it is recommended to check
	# the return of all extern methods implemented in Java to ensure the value
	# is not a Java null. In case it is, you should replace it by a normal Nit
	# `null`.
	fun is_java_null: Bool in "Java" `{ return self == null; `}

	# `JavaString` representation of `self` using Java's `toString`
	fun to_java_string: JavaString in "Java" `{ return self.toString(); `}

	# Use Java's `toString` for any `JavaObject`
	redef fun to_s
	do
		if is_java_null then return "<{inspect_head}:null>"
		return to_java_string.to_s
	end
end

# Java class: java.lang.Throwable
extern class JavaThrowable in "Java" `{ java.lang.Throwable `}
	super JavaObject

	# Java implementation: java.lang.String java.lang.Throwable.getMessage()
	fun message: JavaString in "Java" `{
		return self.getMessage();
	`}

	# Java implementation: java.lang.String java.lang.Throwable.getLocalizedMessage()
	fun localized_message: JavaString in "Java" `{
		return self.getLocalizedMessage();
	`}

	# Java implementation:  java.lang.Throwable.printStackTrace()
	fun print_stack_trace in "Java" `{
		self.printStackTrace();
	`}

	# Java implementation: java.lang.Throwable java.lang.Throwable.getCause()
	fun cause: JavaThrowable in "Java" `{
		return self.getCause();
	`}

	redef fun new_global_ref import sys, Sys.jni_env `{
		Sys sys = JavaThrowable_sys(self);
		JNIEnv *env = Sys_jni_env(sys);
		return (*env)->NewGlobalRef(env, self);
	`}

	redef fun pop_from_local_frame_with_env(jni_env) `{
		return (*jni_env)->PopLocalFrame(jni_env, self);
	`}
end

# Java class: java.lang.Exception
extern class JavaException in "Java" `{ java.lang.Exception `}
	super JavaThrowable

	redef fun new_global_ref import sys, Sys.jni_env `{
		Sys sys = JavaException_sys(self);
		JNIEnv *env = Sys_jni_env(sys);
		return (*env)->NewGlobalRef(env, self);
	`}

	redef fun pop_from_local_frame_with_env(jni_env) `{
		return (*jni_env)->PopLocalFrame(jni_env, self);
	`}
end

redef class JniEnv
	# Create new `Java.nio.ByteBuffer` referring to `address` with the given `capacity` in bytes
	#
	# JNI function: NewDirectByteBuffer
	fun new_direct_byte_buffer(address: Pointer, capacity: Int): Java_nio_ByteBuffer `{
		return (*self)->NewDirectByteBuffer(self, address, capacity);
	`}
end

# Container for data of a specific primitive type
#
# Java class: java.nio.Buffer
extern class Java_nio_Buffer in "Java" `{ java.nio.Buffer `}
	super JavaObject

	# Address pointed by this buffer
	#
	# JNI function: GetDirectBufferAddress
	fun direct_buffer_address(jni_env: JniEnv): Pointer `{
		return (*jni_env)->GetDirectBufferAddress(jni_env, self);
	`}

	# Capacity of this this buffer
	#
	# JNI function: GetDirectBufferCapacity
	fun direct_buffer_capacity(jni_env: JniEnv): Int `{
		return (*jni_env)->GetDirectBufferCapacity(jni_env, self);
	`}
end

# A byte buffer
#
# Java class: java.nio.ByteBuffer
extern class Java_nio_ByteBuffer in "Java" `{ java.nio.ByteBuffer `}
	super Java_nio_Buffer

	# Allocate a new `java.nio.ByteBuffer` with `allocateDirect`
	new direct(size: Int) in "Java" `{
		return java.nio.ByteBuffer.allocateDirect((int)size);
	`}
end
lib/java/ffi_support.nit:15,1--292,3