Mercurial > octave
changeset 24140:0b7662d8bd02
doc: libinterp/octave-value/ov-java.cc: Improve (Doxygen) comments.
Pushed by Kai T. Ohlhus <k.ohlhus@gmail.com>.
author | Ernst Reissner <rei3ner@arcor.de> |
---|---|
date | Fri, 13 Oct 2017 15:32:59 +0200 |
parents | 5d2d0e570e46 |
children | af577de75e68 |
files | libinterp/octave-value/ov-java.cc |
diffstat | 1 files changed, 180 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/octave-value/ov-java.cc Thu Oct 12 23:17:25 2017 +0200 +++ b/libinterp/octave-value/ov-java.cc Fri Oct 13 15:32:59 2017 +0200 @@ -20,6 +20,11 @@ */ + +//! @file ov-java.cc +//! +//! Provides Octave's Java interface. + #if defined (HAVE_CONFIG_H) # include "config.h" #endif @@ -168,15 +173,32 @@ Java_org_octave_Octave_needThreadedInvokation (JNIEnv *, jclass); } +//! The pointer to a java virtual machine either created in the current thread +//! or attached this thread to it. + static JavaVM *jvm = nullptr; + +//! Whether the current thread is attached to the jvm given by #jvm. +//! This is @c false also if no jvm exists, i.e. if #jvm is @c nullptr. +//! @see #initialize_jvm() +//! @see #terminate_jvm() + static bool jvm_attached = false; -// Need to keep hold of the shared library handle until exit. +//! Need to keep hold of the shared library handle until exit. +//! @see #initialize_jvm() +//! @see #terminate_jvm() + static octave::dynamic_library jvm_lib; static std::map<int,octave_value> listener_map; static std::map<int,octave_value> octave_ref_map; static int octave_java_refcount = 0; + +//! The thread id of the currently executing thread or @c -1 if this is +//! unknown. +//! @see #initialize_java() + static long octave_thread_ID = -1; bool Vjava_matrix_autoconversion = false; @@ -335,6 +357,25 @@ #endif +//! The java initialization directory is given by the environment variable +//! @c OCTAVE_JAVA_DIR if defined; otherwise it is the directory of Octave's +//! m-files defining Java functions. +//! +//! The Java initialization directory is the directory where resides: +//! +//! - @c octave.jar, defining the java classes implementing octave's java +//! interface, +//! - @c javaclasspath.txt, defining the installation defined portion of the +//! (static) classpath, +//! - @c java.opts, defining the configurable options of the java virtual +//! machine. +//! +//! Note that the (static) java classpath of the java virtual machine starts +//! with @c octave.jar, and that the static java classpath ends with what +//! is read from @c javaclasspath.txt located in the initial java directory. +//! Moreover, the java virtual machine is created essentially with +//! the options given by @c java.opts. + static std::string initial_java_dir (void) { @@ -352,16 +393,19 @@ return java_dir; } -// Read the content of a file filename (usually "classpath.txt") -// -// Returns a string with all lines concatenated and separated -// by the path separator character. -// The return string also starts with a path separator so that -// it can be appended easily to a base classpath. -// -// The file "classpath.txt" must contain single lines, each -// with a classpath. -// Comment lines starting with a '#' or a '%' in column 1 are allowed. +//! Return the classpath in the given file @c filepath as a string. +//! +//! In the classpath file, each line which is neither empty nor a comment, is +//! interpreted as a segment of a path. Comment lines are those starting with +//! a @c # or with a @c % in the very first column. +//! +//! @param filepath The path to the file (usually @c classpath.txt) containing +//! a portion of the classpath. +//! +//! @returns A string consisting of the lines of @c filepath which are neither +//! comments nor empty without trailing whitespace separated by +//! `octave::directory_path::path_sep_str()`. The returned string also +//! starts with that path separator. static std::string read_classpath_txt (const std::string& filepath) @@ -399,6 +443,25 @@ return (classpath); } + +//! Return the initial classpath. +//! +//! The initial classpath starts with a pointer to @c octave.jar which is +//! located in the initial java directory given by #java_init_dir(). +//! +//! @attention This is nowhere documented and also the script +//! @c javaclasspath.m drops this. On the other hand, this is vital because +//! @c octave.jar contains the java core classes of octave's java interface. +//! +//! The rest of the classpath is read sequentially from files +//! @c javaclasspath.txt located in either: +//! +//! - the current directory, +//! - the user's home directory, +//! - the initial java directory returned by #initial_java_dir() +//! +//! @returns The initial classpath. + static std::string initial_class_path (void) { @@ -406,7 +469,7 @@ std::string retval = java_dir; - // find octave.jar file + // Find octave.jar file. if (! retval.empty ()) { std::string sep = octave::sys::file_ops::dir_sep_str (); @@ -417,7 +480,7 @@ if (jar_exists) { - // initialize static classpath to octave.jar + // Initialize static classpath to octave.jar. retval = jar_file; // The base classpath has been set. @@ -488,10 +551,36 @@ return retval; } +//! Initialize the java virtual machine (jvm) and field #jvm if necessary. +//! +//! If the jvm exists and is initialized, #jvm points to it, i.e. is not 0 +//! and there is nothing to do. +//! +//! If #jvm is 0 and if at least one jvm exists, attach the current thread to +//! it by setting #jvm_attached. Otherwise, create a #jvm with some hard- +//! coded options: +//! +//! - `-Djava.class.path=classpath`, where @c classpath is given by +//! #initial_class_path(). +//! - `-Djava.system.class.loader=org.octave.OctClassLoader`. +//! - `-Xrs` +//! +//! Further options are read from the file @c java.opts in the directory given +//! by #java_init_dir(). +//! +//! Note that #initial_class_path() determines the initial classpath. This +//! is the static classpath which cannot be changed. Elements of the dynamic +//! classpath can be added and removed using the m-file scripts +//! @c javaaddpath.m and @c javarmpath.m. +//! +//! @see #terminate_jvm() + static void initialize_jvm (void) { // Most of the time JVM already exists and has been initialized. + // Also it seems, as if jvm is set, the jvm is already attached. + // This does not fit terminate_jvm. if (jvm) return; @@ -506,8 +595,8 @@ if (hMod) { - // JVM seems to be already loaded, better to use that DLL instead - // of looking in the registry, to avoid opening a different JVM. + // JVM seems to be already loaded, better to use that DLL instead of + // looking in the registry, to avoid opening a different JVM. jvm_lib_path = get_module_filename (hMod); if (jvm_lib_path.empty ()) @@ -554,6 +643,7 @@ #endif + //! The number of created jvm's. jsize nVMs = 0; #if ! defined (__APPLE__) && ! defined (__MACH__) @@ -588,7 +678,7 @@ #endif { - // At least one JVM exists, try to attach to it + // At least one JVM exists, try to attach the current thread to it. switch (jvm->GetEnv (reinterpret_cast<void **> (¤t_env), JNI_VERSION_1_6)) @@ -614,7 +704,6 @@ } jvm_attached = true; - //printf ("JVM attached\n"); } else { @@ -622,9 +711,12 @@ octave::JVMArgs vm_args; + // Hard-coded options for the jvm. vm_args.add ("-Djava.class.path=" + initial_class_path ()); + vm_args.add ("-Djava.system.class.loader=org.octave.OctClassLoader"); vm_args.add ("-Xrs"); - vm_args.add ("-Djava.system.class.loader=org.octave.OctClassLoader"); + + // Additional options given by file java.opts. vm_args.read_java_opts (initial_java_dir () + octave::sys::file_ops::dir_sep_str () + "java.opts"); @@ -650,11 +742,20 @@ setlocale (LC_ALL, locale.c_str ()); } +//! Terminate the current jvm, if there is any. +//! +//! Otherwise, detach the jvm if this thread is attached to it and unload it +//! if this thread created it itself. +//! +//! @see #initialize_jvm() + static void terminate_jvm (void) { + // There is nothing to do if jvm is not set (= nullptr). if (jvm) { + // FIXME: Seems that if jvm_attached is always true if jvm is not null. if (jvm_attached) jvm->DetachCurrentThread (); else @@ -670,6 +771,8 @@ } } +//! Converts a Java string object to std::string. +//!{ static std::string jstring_to_string (JNIEnv *jni_env, jstring s) { @@ -703,6 +806,12 @@ return retval; } +//!} + +//! Returns a reference to the jni (java native interface) environment of the +//! Java virtual machine #jvm. +//! +//! @returns A reference to jni, if #jvm is present, otherwise @c nullptr. static inline JNIEnv * thread_jni_env (void) @@ -734,8 +843,8 @@ #else - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -766,8 +875,8 @@ octave_unused_parameter (cls_name); - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -937,11 +1046,11 @@ jint *buf = jni_env->GetIntArrayElements (i_array, nullptr); // Here, buf points to the beginning of i_array - // Copy v to buf + // Copy v to buf. for (int k = 0; k < v.length (); k++) buf[k] = v(k); - // set retval[i]=i_array + // Set retval[i] = i_array jni_env->ReleaseIntArrayElements (i_array, buf, 0); jni_env->SetObjectArrayElement (retval, i, i_array); @@ -1175,9 +1284,10 @@ //! Convert the Java object pointed to by @c jobj_arg with class @c jcls_arg //! to an Octave value. //! -//! @param jni_env JNI environment pointer -//! @param jobj_arg pointer to a Java object -//! @param jcls_arg optional pointer to the Java class of @c jobj_arg +//! @param jni_env JNI environment pointer. +//! @param jobj_arg Pointer to a Java object. +//! @param jcls_arg Optional pointer to the Java class of @c jobj_arg. +//! //! @return //! @arg numeric value as a @c double if @c jobj_arg is of type @c Byte, //! @c Short, @c Integer, @c Long, @c Float or @c Double @@ -1187,8 +1297,10 @@ //! a Java array of primitive types //! @arg Octave matrix if @c jobj_arg is of type @c org.octave.Matrix and //! #Vjava_matrix_autoconversion is enabled -//! @arg Octave object if @c jobj_arg is of type @c org.octave.OctaveReference -//! @arg @c octave_java object wrapping the Java object otherwise +//! @arg Octave object if @c jobj_arg is of type +//! @c org.octave.OctaveReference +//! @arg @c octave_java object wrapping the Java object otherwise. + static octave_value box (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg) { @@ -1375,7 +1487,7 @@ break; } - // No suitable class found. Return a generic octave_java object + // No suitable class found. Return a generic octave_java object. retval = octave_value (new octave_java (jobj, jcls)); break; } @@ -1740,11 +1852,19 @@ return found; } +//! Returns the id of the current thread. +//! +//! @param jni_env The current environment or @c nullptr. +//! +//! @returns The id of the current thread or -1 otherwise. The latter happens +//! if @c jni_env is @c nullptr, for example. + static long get_current_thread_ID (JNIEnv *jni_env) { if (jni_env) { + // Call Java method static Thread java.lang.Thread.currentThread(). jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/Thread")); jmethodID mID = jni_env->GetStaticMethodID (cls, "currentThread", "()Ljava/lang/Thread;"); @@ -1752,10 +1872,10 @@ if (jthread) { + // Call Java method long java.lang.Thread.getId(). jclass_ref jth_cls (jni_env, jni_env->GetObjectClass (jthread)); mID = jni_env->GetMethodID (jth_cls, "getId", "()J"); long result = jni_env->CallLongMethod (jthread, mID); - //printf ("current java thread ID = %ld\n", result); return result; } } @@ -1763,6 +1883,10 @@ return -1; } +//! Run the java method @c org.octave.Octave.checkPendingAction(). +//! +//! @returns 0 in any case for good reason. + static int java_event_hook (void) { @@ -1770,6 +1894,7 @@ if (current_env) { + // Invoke static void org.octave.Octave.checkPendingAction(). jclass_ref cls (current_env, find_octave_class (current_env, "org/octave/Octave")); jmethodID mID = current_env->GetStaticMethodID @@ -1782,6 +1907,13 @@ return 0; } +//! Initialize java including the virtual machine (jvm) if necessary. +//! +//! Initializes the fields #jvm, #jvm_attached, #jvm_lib, and +//! #octave_thread_ID. To ensure that java is initialized, this method is +//! used as part of octave functions @c javaObject, @c javaMethod, +//! @c __java_get__, @c __java_set__, and @c java2mat. + static void initialize_java (void) { @@ -1796,7 +1928,6 @@ octave::command_editor::add_event_hook (java_event_hook); octave_thread_ID = get_current_thread_ID (current_env); - //printf ("octave thread ID=%ld\n", octave_thread_ID); } catch (std::string msg) { @@ -1894,7 +2025,7 @@ #endif -// octave_java class definition +//! Ctor. octave_java::octave_java (void) : octave_base_value (), java_object (nullptr), java_class (nullptr) @@ -1952,8 +2083,8 @@ #else - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -2017,8 +2148,8 @@ octave_unused_parameter (idx); octave_unused_parameter (nargout); - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -2107,8 +2238,8 @@ octave_unused_parameter (idx); octave_unused_parameter (rhs); - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -2129,8 +2260,8 @@ #else - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -2154,8 +2285,8 @@ octave_unused_parameter (force); octave_unused_parameter (type); - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -2263,8 +2394,8 @@ octave_unused_parameter (name); octave_unused_parameter (args); - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); @@ -2757,16 +2888,16 @@ #else - // This shouldn't happen because construction of octave_java - // objects is supposed to be impossible if Java is not available. + // This shouldn't happen because construction of octave_java objects is + // supposed to be impossible if Java is not available. panic_impossible (); #endif } -// DEFUN blocks below must be outside of HAVE_JAVA block so that -// documentation strings are always available, even when functions are not. +// DEFUN blocks below must be outside of HAVE_JAVA block so that documentation +// strings are always available, even when functions are not. DEFUN (__java_init__, , , doc: /* -*- texinfo -*-